2012-07-12 18 views
9

¿Es posible tener múltiples servlets jersey en un solo web.xml? Estoy tratando de hacer el control de versiones Restfull de esta manera:Servlets de mallas múltiples en un solo web.xml

<?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> 

Pero la primavera contexto-v1 y v2 contexto se debe cargar por separado? Debido a que tienen granos, que tienen el mismo nombre, etc.

EDIT:

Si nos fijamos en mi salida de la consola que está cargando los recursos (admin/info) dos veces para cada 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 debería - si recuerdo bien - sea 1 en ambos casos –

+0

no, no es cierto, es la secuencia de inicio de los servlets ... – Ben

Respuesta

9

Sí, puede especificar dos o más servlets en un web.xml. Recuerde especificar un mapeo de servlet diferente para cada uno.

<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> 

la initParameter loadOnStartup define el orden en el que se carga el servlet (en este caso primero servletOne y luego servletTwo).

+0

eso es verdad, ambos servlets están cargados .. pero tome una mira mi salida de consola mi problema es que mis recursos (AdminResource, InfoResource) se cargan dos veces para cada servlet ... – Ben

+0

mmm ... extraño ya que has definido dos paquetes diferentes ... en alternativa podrías tratar de definir Servlet y Servidor programáticamente (como el código definido aquí http://stackoverflow.com/questions/11210734/jersey-on-jetty-on-android-throws-containerexception-the-resourceconfig-instanc en la actividad de inicio del servidor Android) – Giorgio

+0

Este no es el correcto ¡responder! Spring cargará todas las clases anotadas que encuentre en el contexto principal sin importar lo que pongas aquí. Por lo tanto, tendrá dos servlets que servirán las mismas cosas exactamente. ¡Cuidado y pruébalo! La respuesta correcta está arriba ... – markthegrea

6

El hecho es que cuando usa Jersey y Spring juntos, el servlet Jersey/Spring pasa por todos los beans Spring disponibles y registra todas las clases de recursos y proveedores que encontrará entre ellos.

Si tiene varios servlets Jersey/Spring que usan el mismo contexto (raíz) y comparten las definiciones de bean, entonces el procedimiento se realiza para cada servlet y el recurso y la clase de proveedor se registran varias veces.

Para evitar el registro múltiple del mismo bean, defina dichos beans en un contexto secundario de su respectivo servlet Jesrey/Spring.

Ni siquiera es necesario proporcionar parámetros de inicialización para declarar clases en el web.xml a menos que se requiera una combinación de clases administradas por Spring y administradas por Jersey.

<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

Esta debería ser la respuesta seleccionada. – manikanta

1

Sé que este tema es antiguo para responder. Pero mi respuesta puede ayudar a otros.

Podemos configurar varios paquetes de recursos en web.xml con estos delimitadores:

  1. espacio blanco
  2. coma (,)
  3. punto y coma (;)
  4. Nextline

Ejemplo:

<?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

Una posibilidad más es anular un método en com.sun.jersey.spi.spring.container.servlet.SpringServlet. El método initiate se ve así (versión 1.19.1):

@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; 
    } 
} 

Si cambia el código en una subclase de esta manera, a continuación, puede filtrar los granos de primavera no deseados en base a sus criterios (por ejemplo de nombre de paquete):

@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; 
    } 
} 

Un bit solución hacky, pero funciona para nosotros a la perfección.

Cuestiones relacionadas