2016-10-14 2 views
2

Servlet 3.x 컨테이너에서 Jersey 서블릿 컨테이너 (2.x) 설명자없이 javax.servlet.Filter으로 실행하는 방법이 있습니까? 나는 필터로 실행할 때 jersey.config.servlet.filter.forwardOn404 또는 jersey.config.servlet.filter.staticContentRegex가있는 경우에만 자바 독서블릿 3.x 컨테이너에서 서술자없는 Jersey 서블릿 컨테이너가 필터로 실행됩니다.

속성은 저지 서블릿 컨테이너는 모두 javax로 실행하도록 구성된 경우에만 적용에 따라 작업을 사용해야하므로 내 서비스와 함께 정적 리소스를 제공하고 필요 .servlet.Filter. 그렇지 않으면이 등록 정보가 무시됩니다.

내가 원하는 내 사용자 정의 Application 클래스의 web.xml 완전히

<?xml version="1.0" encoding="UTF-8"?> 
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee 
      http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" 
    version="3.1"> 
    <display-name>My-Webservice</display-name> 

    <filter> 
     <filter-name>Jersey Filter</filter-name> 
     <filter-class>org.glassfish.jersey.servlet.ServletContainer</filter-class> 
     <init-param> 
      <param-name>javax.ws.rs.Application</param-name> 
      <param-value>com.foo.webservices.MyApplication</param-value> 
     </init-param> 
    </filter> 
</web-app> 

제거하고 모든 것을 가지고 얻을 수 있습니다

@ApplicationPath(value = "/") 
public class MyApplication extends ResourceConfig 
{  
    public MyApplication() 
    { 
     packages("com.foo.webservices.services"); 
     property(ServletProperties.FILTER_FORWARD_ON_404, true); 
    } 
} 

공식 문서 (https://jersey.java.net/documentation/latest/deployment.html#deployment.servlet.3이) 아무것도 언급하지 않습니다 불행히도 필터에 대해서.

답변

2

그것은 가능합니다. 다만 설정 속성을 설정하는 것만 큼 쉽지는 않을 것입니다. 그것이 실제로 어떻게 작동하는지 조금 이해하면 도움이 될 것입니다. Servlet 3.x에서는 서블릿을 동적으로로드하기 위해 구현할 수있는 ServletContainerInitializer을 도입했습니다 (자세한 내용은 here 참조). Jersey에는 사용되는 구현이 있습니다. 그러나 JAX-RS는 애플리케이션이 서블릿으로로드되어야한다고 말합니다. 그래서 저지는이 문제를 둘러싼 어떠한 제안도하지 않습니다.

우리는 우리 자신의 ServletContainerInitializer을 쓸 수도 있고, Jersey 's를 이용할 수도 있습니다. Jersey는 SerletContainerProvider을 구현할 수 있습니다. 우리는 서블릿 필터를 직접 등록해야합니다. 우리는 우리의 구현을 일단 구현이

@Override 
public void preInit(ServletContext context, Set<Class<?>> classes) throws ServletException { 
    final Class<? extends Application> applicationCls = getApplicationClass(classes); 
    if (applicationCls != null) { 
     final ApplicationPath appPath = applicationCls.getAnnotation(ApplicationPath.class); 
     if (appPath == null) { 
      LOGGER.warning("Application class is not annotated with ApplicationPath"); 
      return; 
     } 
     final String mapping = createMappingPath(appPath); 
     addFilter(context, applicationCls, classes, mapping); 
     // to stop Jersey servlet initializer from trying to register another servlet 
     classes.remove(applicationCls); 
    } 
} 

private static void addFilter(ServletContext context, Class<? extends Application> cls, 
           Set<Class<?>> classes, String mapping) { 
    final ResourceConfig resourceConfig = ResourceConfig.forApplicationClass(cls, classes); 
    final ServletContainer filter = new ServletContainer(resourceConfig); 
    final FilterRegistration.Dynamic registration = context.addFilter(cls.getName(), filter); 
    registration.addMappingForUrlPatterns(null, true, mapping); 
    registration.setAsyncSupported(true); 
} 

처럼 보일 것입니다, 우리는 클래스 패스의 루트에 있어야 파일

META-INF/services/org.glassfish.jersey.servlet.internal.spi.ServletContainerProvider 

을 작성해야합니다. 해당 파일의 내용은 우리 구현의 완전한 이름이어야합니다.

당신이 GitHub Repo

+0

멋진 대답 완전한 예를 볼 수 있습니다, 감사합니다. 응용 프로그램 클래스로'org.glassfish.jersey.server.ResourceConfig $ RuntimeConfig'를 잘못 판단한 것처럼 getApplicationClass 메소드에 다른 검사를 추가해야했습니다. 방금 break 문에 if (applicationCls! = null && applicationCls.getAnnotation (ApplicationPath.class)! = null)'을 추가했습니다. – lazlev