Jersey ContainerRequestFilter 未触发

Posted

技术标签:

【中文标题】Jersey ContainerRequestFilter 未触发【英文标题】:Jersey ContainerRequestFilter not triggered 【发布时间】: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>

【问题讨论】:

【参考方案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】:

一些提示:

    确保您使用的是 JAX-RS 2.17 版。

    确保您在过滤器中使用了正确的导入:

    import javax.ws.rs.container.ContainerRequestContext; import javax.ws.rs.container.ContainerRequestFilter;

    添加@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 将只加载指定命名空间中标记的类

以上是关于Jersey ContainerRequestFilter 未触发的主要内容,如果未能解决你的问题,请参考以下文章

Jersey:是不是可以覆盖 Jersey filter() 的返回类型?

将使用 jersey 1.x 的 java 代码转换为 jersey 2.x

Jersey

在 jersey 项目中包含 jersey-bom 导入范围依赖项的目的是啥?

JDK1.6使用jersey多少版本

Eclipse + Jersey 发布RESTful WebService了解Jersey