2012-07-12 46 views
9

是否可以在一個web.xml中包含多個球衣servlets?我試圖用這種方式做RESTfull版本控制:一個web.xml中有多個球衣servlets

<?xml version="1.0" encoding="UTF-8"?> 
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5"> 

    <display-name>myapi</display-name> 

    <context-param> 
    <param-name>contextConfigLocation</param-name> 
    <param-value>/WEB-INF/context-v1.xml /WEB-INF/context-v2.xml</param-value> 
    </context-param> 

    <listener> 
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> 
    </listener> 

    <servlet> 
    <servlet-name>REST-V1</servlet-name> 
    <servlet-class>com.sun.jersey.spi.spring.container.servlet.SpringServlet</servlet-class> 
    <init-param> 
     <param-name>com.sun.jersey.config.property.packages</param-name> 
     <param-value>com.myapi.rest.v1</param-value> 
    </init-param> 
    <load-on-startup>1</load-on-startup> 
    </servlet> 

    <servlet-mapping> 
    <servlet-name>REST-V1</servlet-name> 
    <url-pattern>/v1/*</url-pattern> 
    </servlet-mapping> 

    <servlet> 
    <servlet-name>REST-V2</servlet-name> 
    <servlet-class>com.sun.jersey.spi.spring.container.servlet.SpringServlet</servlet-class> 
    <init-param> 
     <param-name>com.sun.jersey.config.property.packages</param-name> 
     <param-value>com.myapi.rest.v2</param-value> 
    </init-param> 
    <load-on-startup>2</load-on-startup> 
    </servlet> 

    <servlet-mapping> 
    <servlet-name>REST-V2</servlet-name> 
    <url-pattern>/v2/*</url-pattern> 
    </servlet-mapping> 

    <welcome-file-list> 
    <welcome-file>index.html</welcome-file> 
    </welcome-file-list> 

</web-app> 

但是,spring context-v1和context-v2應該分開加載嗎?因爲他們有豆類,它們具有相同的名稱等

編輯:

如果你在我的控制檯輸出它加載的資源(管理/ INFO)兩次,每次servlet的樣子:

15.07.2012 14:47:08 com.sun.jersey.api.core.PackagesResourceConfig init 
INFO: Scanning for root resource and provider classes in the packages: 
    com.myapi.rest.v1 
15.07.2012 14:47:08 com.sun.jersey.api.core.ScanningResourceConfig logClasses 
INFO: Root resource classes found: 
    class com.myapi.rest.v1.LOAdminResource 
    class com.myapi.rest.v1.LOInfoResource 
15.07.2012 14:47:08 com.sun.jersey.api.core.ScanningResourceConfig init 
INFO: No provider classes found. 
15.07.2012 14:47:09 com.sun.jersey.spi.spring.container.servlet.SpringServlet getContext 
INFO: Using default applicationContext 
15.07.2012 14:47:09 com.sun.jersey.spi.spring.container.SpringComponentProviderFactory registerSpringBeans 
INFO: Registering Spring bean, adminResource_v2, of type com.myapi.rest.v2.LOAdminResource as a root resource class 
15.07.2012 14:47:09 com.sun.jersey.spi.spring.container.SpringComponentProviderFactory registerSpringBeans 
INFO: Registering Spring bean, infoResource_v2, of type com.myapi.rest.v2.LOInfoResource as a root resource class 
15.07.2012 14:47:09 com.sun.jersey.spi.spring.container.SpringComponentProviderFactory registerSpringBeans 
INFO: Registering Spring bean, adminResource_v1, of type com.myapi.rest.v1.LOAdminResource as a root resource class 
15.07.2012 14:47:09 com.sun.jersey.spi.spring.container.SpringComponentProviderFactory registerSpringBeans 
INFO: Registering Spring bean, infoResource_v1, of type com.myapi.rest.v1.LOInfoResource as a root resource class 
15.07.2012 14:47:09 com.sun.jersey.server.impl.application.WebApplicationImpl _initiate 
INFO: Initiating Jersey application, version 'Jersey: 1.8 06/24/2011 12:17 PM' 
15.07.2012 14:47:09 com.sun.jersey.api.core.PackagesResourceConfig init 
INFO: Scanning for root resource and provider classes in the packages: 
    com.myapi.rest.v2 
15.07.2012 14:47:09 com.sun.jersey.api.core.ScanningResourceConfig logClasses 
INFO: Root resource classes found: 
    class com.myapi.rest.v2.LOAdminResource 
    class com.myapi.rest.v2.LOInfoResource 
15.07.2012 14:47:09 com.sun.jersey.api.core.ScanningResourceConfig init 
INFO: No provider classes found. 
15.07.2012 14:47:09 com.sun.jersey.spi.spring.container.servlet.SpringServlet getContext 
INFO: Using default applicationContext 
15.07.2012 14:47:09 com.sun.jersey.spi.spring.container.SpringComponentProviderFactory registerSpringBeans 
INFO: Registering Spring bean, adminResource_v2, of type com.myapi.rest.v2.LOAdminResource as a root resource class 
15.07.2012 14:47:09 com.sun.jersey.spi.spring.container.SpringComponentProviderFactory registerSpringBeans 
INFO: Registering Spring bean, infoResource_v2, of type com.myapi.rest.v2.LOInfoResource as a root resource class 
15.07.2012 14:47:09 com.sun.jersey.spi.spring.container.SpringComponentProviderFactory registerSpringBeans 
INFO: Registering Spring bean, adminResource_v1, of type com.myapi.rest.v1.LOAdminResource as a root resource class 
15.07.2012 14:47:09 com.sun.jersey.spi.spring.container.SpringComponentProviderFactory registerSpringBeans 
INFO: Registering Spring bean, infoResource_v1, of type com.myapi.rest.v1.LOInfoResource as a root resource class 
15.07.2012 14:47:09 com.sun.jersey.server.impl.application.WebApplicationImpl _initiate 
INFO: Initiating Jersey application, version 'Jersey: 1.8 06/24/2011 12:17 PM' 
+0

load-on-startup應該 - 如果我記得正確 - 在這兩種情況下都是1 – 2012-07-12 21:42:36

+0

不,它不是真的,它的servlet啓動順序... – Ben 2012-07-15 12:50:21

回答

9

是的,您可以在web.xml中指定兩個或多個servlet。請記住爲每一個指定一個不同的servlet映射。

<servlet> 
    <servlet-name>servletOne</servlet-name> 
    <servlet-class>com.sun.jersey.spi.spring.container.servlet.SpringServlet</servlet-class> 
    <init-param> 
    <param-name>com.sun.jersey.config.property.packages</param-name> 
    <param-value>com.packageOne</param-value> 
    </init-param> 
    <load-on-startup>1</load-on-startup> 
</servlet> 
<servlet> 
    <servlet-name>servletTwo</servlet-name> 
    <servlet-class>com.sun.jersey.spi.spring.container.servlet.SpringServlet</servlet-class> 
    <init-param> 
    <param-name>com.sun.jersey.config.property.packages</param-name> 
    <param-value>com.packageTwo</param-value> 
    </init-param> 
    <load-on-startup>2</load-on-startup> 
</servlet> 

<servlet-mapping> 
    <servlet-name>ServletOne</servlet-name> 
    <url-pattern>/v1/*</url-pattern> 
</servlet-mapping> 
    <servlet-mapping> 
    <servlet-name>ServletTwo</servlet-name> 
<url-pattern>/v2/*</url-pattern> 
</servlet-mapping> 

的initParameter loadOnStartup定義(在這種情況下,第一servletOne然後servletTwo),在該小服務程序被加載的順序。

+0

這是真的,兩個servlet都加載了..但是拿一個看看我的控制檯輸出。我的問題是,我的資源(AdminResource,InfoResource)加載了兩次,每個servlet ... – Ben 2012-07-15 13:08:33

+0

mmm ...奇怪,因爲我已經定義了兩個不同的包... 替代方法,你可以嘗試定義服務器和Servlet以編程方式(如在這裏定義的代碼http://stackoverflow.com/questions/11210734/jersey-on-jetty-on-android-throws-containerexception-the-resourceconfig-instanc在啓動服務器Android活動下) – Giorgio 2012-07-15 19:01:36

+0

這不是正確的回答!無論你在這裏放置什麼,Spring都會加載它在主要上下文中找到的每個帶註釋的類。所以你將有兩個servlet可以提供完全相同的東西。謹防並嘗試!正確答案在上面... – markthegrea 2014-12-21 13:53:32

6

的事情是,當你使用新澤西州和春天一起,澤西/春天的servlet經過所有可用的Spring bean和一切資源和提供者類,將其中找到註冊。

如果您在使用相同(根)範圍內的多個州/春servlet和這樣就共享bean定義,則該過程對於每一個這樣的servlet和資源提供者類進行註冊幾次。

爲了避免相同的bean的多重註冊,在相應的Jesrey /彈簧的servlet的子上下文定義這種豆。

它甚至沒有必要,除非是必需的Spring管理和澤西管理類的混合物在web.xml中聲明類提供初始化參數。

<context-param> 
    <param-name>contextConfigLocation</param-name> 
    <param-value>/WEB-INF/root-context.xml</param-value> 
</context-param> 

... 

<servlet> 
    <servlet-name>REST-V1</servlet-name> 
    <servlet-class>com.sun.jersey.spi.spring.container.servlet.SpringServlet</servlet-class> 
    <init-param> 
     <param-name>contextConfigLocation</param-name> 
     <param-value>/WEB-INF/context-v1.xml</param-value> 
    </init-param> 
    <load-on-startup>1</load-on-startup> 
</servlet> 

<servlet> 
    <servlet-name>REST-V2</servlet-name> 
    <servlet-class>com.sun.jersey.spi.spring.container.servlet.SpringServlet</servlet-class> 
    <init-param> 
     <param-name>contextConfigLocation</param-name> 
     <param-value>/WEB-INF/context-v1.xml /WEB-INF/context-v2.xml</param-value> 
    </init-param> 
    <load-on-startup>2</load-on-startup> 
</servlet> 

... 
+0

這應該是選定的答案。 – manikanta 2015-09-18 17:56:09

1

我知道這個話題是老的回答。但我的回答可以幫助其他人。

我們可以在web.xml配置多個資源封裝,這些分隔符:

  1. 空白
  2. 逗號(,)
  3. 分號(;)
  4. Nextline

實施例:

<?xml version="1.0" encoding="UTF-8"?> 
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0"> 
    <display-name>MultiplePackageRest</display-name> 
    <servlet> 
    <servlet-name>JerseyMultiplePackage</servlet-name> 
    <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class> 
    <init-param> 
     <param-name>jersey.config.server.provider.packages</param-name> 
     <param-value>info.javadoff.rest1,info.javadoff.rest2,...</param-value> 
    </init-param> 
     <load-on-startup>1</load-on-startup> 
    </servlet> 
    <servlet-mapping> 
    <servlet-name>JerseyMultiplePackage</servlet-name> 
    <url-pattern>/api/*</url-pattern> 
    </servlet-mapping> 
</web-app> 
1

還有一個可能性是在com.sun.jersey.spi.spring.container.servlet.SpringServlet覆蓋的一種方法。啓動方法看起來像這樣(版本1.19。1):

@Override 
protected void initiate(ResourceConfig rc, WebApplication wa) { 
    try { 
     SpringComponentProviderFactory springComponentProviderFactory = new SpringComponentProviderFactory(rc, getContext()); 
     rc.getClasses().removeIf(clazz -> clazz.getPackage().getName().startsWith("bla")); 
     wa.initiate(rc, springComponentProviderFactory); 
    } catch (RuntimeException e) { 
     LOGGER.log(Level.SEVERE, "Exception occurred when intialization", e); 
     throw e; 
    } 
} 

了一下:

@Override 
protected void initiate(ResourceConfig rc, WebApplication wa) { 
    try { 
     wa.initiate(rc, new SpringComponentProviderFactory(rc, getContext())); 
    } catch (RuntimeException e) { 
     LOGGER.log(Level.SEVERE, "Exception occurred when intialization", e); 
     throw e; 
    } 
} 

如果你在這樣的子類更改代碼,那麼你可以根據你的條件(例如包名)過濾掉不需要的春天豆哈克解決方案,但完美的作品。