복붙노트

[SPRING] 하나의 web.xml에 다중 저지 서블릿

SPRING

하나의 web.xml에 다중 저지 서블릿

하나의 web.xml에 여러 개의 저지 서블릿을 포함 할 수 있습니까? 이런 식으로 RESTfull 버전 관리를하려고합니다.

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

그러나 스프링 컨텍스트 -v1과 컨텍스트 -v2는 별도로로드해야합니까? 그들에는 동일한 이름이있는 콩이 있기 때문에.

편집하다:

내 콘솔 출력을 보면 각 서블릿에 대해 리소스 (admin / info)가 두 번로드됩니다.

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'

해결법

  1. ==============================

    1.예, 두 개 이상의 서블릿을 web.xml에 지정할 수 있습니다. 각각에 대해 다른 서블릿 매핑을 지정하는 것을 잊지 마십시오.

    예, 두 개 이상의 서블릿을 web.xml에 지정할 수 있습니다. 각각에 대해 다른 서블릿 매핑을 지정하는 것을 잊지 마십시오.

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

  2. ==============================

    2.Jersey와 Spring을 함께 사용하면 Jersey / Spring 서블릿은 사용 가능한 모든 Spring Bean을 탐색하고 그 중에서 찾을 수있는 모든 리소스와 공급자 클래스를 등록합니다.

    Jersey와 Spring을 함께 사용하면 Jersey / Spring 서블릿은 사용 가능한 모든 Spring Bean을 탐색하고 그 중에서 찾을 수있는 모든 리소스와 공급자 클래스를 등록합니다.

    동일한 (루트) 컨텍스트를 사용하여 여러 개의 Jersey / Spring 서블릿을 만들고 Bean 정의를 공유하는 경우 해당 서블릿에 대해 프로 시저가 수행되고 리소스 및 공급자 클래스가 여러 번 등록됩니다.

    같은 bean을 여러 번 등록하지 않으려면 해당 Jersey / Spring 서블릿의 하위 컨텍스트에서 그러한 bean을 정의하십시오.

    Spring 관리 클래스와 Jersey 관리 클래스가 혼합되어 있지 않으면 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>
    
    ...
    
  3. ==============================

    3.나는이 주제가 대답하기에는 오래되었다는 것을 알고있다. 하지만 내 대답은 다른 사람들을 도울 수 있습니다.

    나는이 주제가 대답하기에는 오래되었다는 것을 알고있다. 하지만 내 대답은 다른 사람들을 도울 수 있습니다.

    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_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>
    
  4. ==============================

    4.한 가지 더 가능한 방법은 com.sun.jersey.spi.spring.container.servlet.SpringServlet의 한 메서드를 재정의하는 것입니다. 초기화 메소드는 다음과 같습니다 (버전 1.19.1).

    한 가지 더 가능한 방법은 com.sun.jersey.spi.spring.container.servlet.SpringServlet의 한 메서드를 재정의하는 것입니다. 초기화 메소드는 다음과 같습니다 (버전 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;
        }
    }
    

    이와 같이 하위 클래스의 코드를 변경하면 기준 (예 : 패키지 이름)을 기반으로 원치 않는 스프링 빈을 필터링 할 수 있습니다.

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

    조금 해키 한 해결책이지만 우리를 위해 완벽하게 작동합니다.

  5. from https://stackoverflow.com/questions/11460977/multiple-jersey-servlets-in-one-single-web-xml by cc-by-sa and MIT license