【问题标题】:Jersey ContainerRequestFilter not triggeredJersey ContainerRequestFilter 未触发
【发布时间】:2013-06-22 10:05:20
【问题描述】:

我正在尝试使用 ContainerRequestFilter 对基于 Tomcat 的 Jersey 应用程序执行一些身份验证。我关注了this document。 问题:过滤器永远不会被触发

过滤器类:

@Provider
public class AuthFilter implements ContainerRequestFilter {

    @Override
    public void filter(ContainerRequestContext requestContext)
        throws IOException {

        // MY AUTHENTICATION CODE GOES HERE

    }

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="debate-rest"
    version="3.0">
  <display-name>rest</display-name>
   <servlet>  
    <servlet-name>Jersey REST Service</servlet-name>  
    <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>  
    <init-param>
        <param-name>com.sun.jersey.spi.container.ContainerRequestFilters</param-name>
        <param-value>com.hck.debate.rest.security.AuthFilter</param-value>
    </init-param>
    <init-param>  
      <param-name>jersey.config.server.provider.packages</param-name>  
      <param-value>com.hck.debate.rest.controller</param-value>  
    </init-param>  
    <init-param>  
        <param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>  
        <param-value>true</param-value>  
    </init-param>      
    <load-on-startup>1</load-on-startup>  
  </servlet>  
  <servlet-mapping>  
    <servlet-name>Jersey REST Service</servlet-name>  
    <url-pattern>/*</url-pattern>  
  </servlet-mapping>

【问题讨论】:

    标签: jersey jersey-2.0


    【解决方案1】:

    我们在 ResourceConfig 实现类中缺少以下调用:

    register(CorrelationIdFilter.class);
    

    【讨论】:

      【解决方案2】:

      我对 JAX-RS 2 有同样的问题,球衣和下面的注释修复了它

       @PreMatching
      

      【讨论】:

      • 但这会改变语义!添加此方法会影响何时调用过滤器。我严重怀疑这会改变任何东西的配置!
      • 谢谢,这正是我所需要的。
      【解决方案3】:

      对于在 MULE ESB 中遇到此问题的任何人。 记得注册路径:

      <jersey:resources doc:name="REST">
         <component doc:name="rest component">
           <spring-object bean="endpoit"/>
         </component>
         <jersey:package packageName="path @Provider-s"/>
      </jersey:resources >
      

      【讨论】:

        【解决方案4】:

        如果您像我一样被卡住,请注意 TomEE 1.7.X 使用 JAX-RS 1.1,它不包括 ContainerRequestFilter。

        【讨论】:

          【解决方案5】:

          好吧,我没明白jersey.config.server.provider.packages init 参数不仅需要引用服务类(API 端点),还需要引用所有类,包括过滤器。

          现在可以了:

          <init-param>  
            <param-name>jersey.config.server.provider.packages</param-name>  
            <param-value>com.hck.debate.rest.controller;com.hck.debate.rest.security</param-value>
          </init-param>
          <init-param>
              <param-name>com.sun.jersey.spi.container.ContainerRequestFilters</param-name>
              <param-value>com.hck.debate.rest.security.AuthFilter</param-value>
          </init-param>
          

          【讨论】:

          • 你上面的代码和 TomCat 一样工作,也许它和 Glas Fish 不同
          • 默认行为是递归扫描,所以你也可以只使用单个基础包com.hck.debate.rest
          • 还要注意com.sun.jersey.spi.container.ContainerRequestFilterscom.sun.jersey.api.json.POJOMappingFeature是没用的。这些是 Jersey 1.x 属性。它们对 Jersey 2.x 没有影响
          • 另请注意,默认情况下,包扫描是递归的。所以不用列出多个包,只需声明一个基本包,如com.hck.debate.rest,它会递归扫描所有子包。
          • 仅供参考,扫描是为了获取带有@Provider@Path 注释的类,因此您需要确保还具有@Provider 注释。
          【解决方案6】:

          我使用了 com.sun.jersey 而不是 javax.ws.rs,它可以工作

          import com.sun.jersey.spi.container.ContainerRequestFilter import com.sun.jersey.spi.container.ContainerRequest

          Dropwizard 用户需要这样做

          environment.jersey().getResourceConfig()
                     .getContainerRequestFilters()
                     .add(filter);
          

          【讨论】:

          • 从而创建依赖于你不应该依赖的包的代码。
          【解决方案7】:

          您可以使用JerseyServletFactory 手动注册ContainerRequestFilter,而不是使用@Provider 注释:

          JerseyServletFactory jerseyServletFactory = new JerseyServletFactory(config);
          HttpServlet myServiceServlet = jerseyServletFactory.create(myResource);
          
          // Register your ContainerRequestFilter like this
          jerseyServletFactory.addRequestFilter(new MyFilter());
          
          httpServer.register(myServiceServlet, "/api");
          httpServer.start();
          

          【讨论】:

          • 这段代码应该放在哪里?
          • @jon 在初始化期间。我将我的代码放在JettyHttpServer 的创建和开始之间,以及需要在开始时初始化的其他内容(数据源、资源、DAO 等)
          • 我也做了同样的事情,现在我想调用 servlet 的销毁(用于一些自定义清理任务)。我无法获取此过滤器的引用以在关闭事件中调用销毁。
          【解决方案8】:

          一些提示:

          1. 确保您使用的是 JAX-RS 2.17 版。
          2. 确保您在过滤器中使用了正确的导入:

            • import javax.ws.rs.container.ContainerRequestContext;
            • import javax.ws.rs.container.ContainerRequestFilter;
          3. 添加@Provider注解

          【讨论】:

          • “@Provider”真的有必要吗?
          • 是的,它将组件注释为某物的提供者。它用于扩展基本的 JAX-RS 功能。
          【解决方案9】:

          我还必须将 @Provider JAX-RS 注释添加到我的过滤器中。
          这使得过滤器可以在 JAX-RS 扫描阶段被发现。

          @Provider
          public class MyAppFilter implements ContainerRequestFilter {
              // filter logic
          }
          

          【讨论】:

          • 这里没有注释什么都没有发生
          • “@Provider”真的有必要吗?
          • 是的,我只需要添加@Provider 注释。包裹扫描已正确设置
          【解决方案10】:

          将过滤器与球衣搭配使用的最低要求:

          • 为过滤器类添加@Provider注解
          • 过滤器类的命名空间必须包含在'jersey.config.server.provider.packages' init-param中

          不需要任何其他设置(例如,'com.sun.jersey.spi.container.ContainerRequestFilters' init-param 或 ResourceConfig)

          【讨论】:

          • “@Provider”真的有必要吗?
          • 是的。 Jersey 将只加载指定命名空间中标记的类
          猜你喜欢
          • 1970-01-01
          • 2016-04-11
          • 1970-01-01
          • 1970-01-01
          • 2011-04-14
          • 1970-01-01
          • 2014-08-12
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多