Java 拦截 JAX-RS 请求:向 tomcat 注册一个 ContainerRequestFilter

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/21556961/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 09:21:54  来源:igfitidea点击:

Intercept JAX-RS Request: Register a ContainerRequestFilter with tomcat

javaweb-servicesresttomcatjax-rs

提问by ulrich

I am trying to intercept a request to my JAX-RS webservice by a ContainerRequestFilter. I want to use it with a custom annotation, so I can decorate certain methods of the webservice. This should enable me to handle requests to this methods based on the information whether they are made on a secure channel or not, before the actual method is executed.

我正在尝试通过 ContainerRequestFilter 拦截对我的 JAX-RS web 服务的请求。我想将它与自定义注释一起使用,这样我就可以装饰 webservice 的某些方法。这应该使我能够在执行实际方法之前,根据这些方法是否在安全通道上发出的信息来处理对这些方法的请求。

I tried different approaches, searched several posts and then implemented mostly based on the answer by Alden in this post. But I can't get it working.

我尝试了不同的方法,搜索了几个帖子,然后主要根据 Alden 在这篇文章中的回答来实现。但我无法让它工作。

I have a method test in my webservice decorated with my custom annotation Ssl.

我在用我的自定义注释 Ssl 装饰的 web 服务中有一个方法测试。

@POST
@Path("/test")
@Ssl
public static Response test(){      
    System.out.println("TEST ...");
}

The annotation looks like this:

注释如下所示:

@NameBinding
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE, ElementType.METHOD })
public @interface Ssl {}

Then I setup a filter implementation

然后我设置了一个过滤器实现

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

@Ssl
@Provider
public class SslInterceptor implements ContainerRequestFilter
{
    @Override
    public void filter(ContainerRequestContext requestContext) throws IOException
    {       
        System.out.println("Filter executed.");
    }
}

But the filter is never executed nor there occur any error messages or warnings. The test method runs fine anyway.

但是过滤器永远不会执行,也不会出现任何错误消息或警告。无论如何,测试方法运行良好。

To resolve it, I tried to register the filter in the web.xml as described here.

为了解决这个问题,我尝试按照此处所述web.xml 中注册过滤器。

<servlet>
    <servlet-name>Jersey Web Application</servlet-name>
    <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>

    <init-param>
      <param-name>com.sun.jersey.config.property.resourceConfigClass</param-name>
      <param-value>com.sun.jersey.api.core.PackagesResourceConfig</param-value>
    </init-param>

    <init-param>
      <param-name>com.sun.jersey.config.property.packages</param-name>
      <param-value>com.my.packagewithfilter</param-value>
    </init-param>

    <init-param>
        <param-name>com.sun.jersey.spi.container.ContainerRequestFilters</param-name>
        <param-value>com.my.packagewithfilter.SslInterceptor</param-value>
    </init-param>

    <init-param>  
      <param-name>jersey.config.server.provider.packages</param-name>  
      <param-value>com.my.packagewithfilter</param-value>
    </init-param>    

  </servlet>

But that also doesn't work. What am I missing? Any ideas how to make that filter work? Any help is really appreciated!

但这也行不通。我错过了什么?任何想法如何使该过滤器工作?任何帮助真的很感激!

采纳答案by Michal Gajdos

You're using JAX-RS 2.0 APIs (request filters, name binding, ...) in your classes but Jersey 1 proprietary init params in your web.xml(package starting with com.sun.jersey, Jersey 2 uses org.glassfish.jersey). Take a look at this answerand at these articles:

您在类中使用 JAX-RS 2.0 API(请求过滤器、名称绑定等),但在您的类中使用 Jersey 1 专有初始化参数web.xml(包以 开头com.sun.jersey,Jersey 2 使用org.glassfish.jersey)。看看这个答案和这些文章:

回答by ACV

Have a look at this blog postfor the more 'classical' approaches (without using the annotation)

查看此博客文章以了解更“经典”的方法(不使用注释)

回答by Vitorlui

Just compiling the answer from Michael Gajdos to help someone who do not want open more tabs:

只是编译 Michael Gajdos 的答案来帮助那些不想打开更多标签的人:

When you are using Jersey-2 you must use the follow configuration to register your filter into the web.xml

当您使用 Jersey-2 时,您必须使用以下配置将过滤器注册到 web.xml 中

jersey.config.server.provider.classnames

jersey.config.server.provider.classnames

instead of

代替

com.sun.jersey.spi.container.ContainerRequestFilters(jersey-1x)

com.sun.jersey.spi.container.ContainerRequestFilters(jersey-1x)

 <!-- This is the config needed -->
<servlet>    
      //...         
     <init-param>
         <param-name>jersey.config.server.provider.classnames</param-name>
         <param-value>com.your_package_path.yourClassFilter</param-value>
     </init-param>
      //...
</servlet>