【问题标题】:Jersey 2: filters and @Context injectionsJersey 2:过滤器和@Context 注入
【发布时间】:2015-11-10 14:38:43
【问题描述】:

我有以下问题:

ContainerRequestFilter 是一个单例,但请阅读:

Jaxrs-2_0 Oracle Spec

在第 9.2 章中,他们说:

上下文特定于特定请求,但某些 JAX-RS 组件的实例(提供者和具有除每个请求之外的生命周期的资源类)可能需要支持多个并发请求。当注入第 9.2 节中列出的类型之一的实例时,提供的实例必须能够为特定请求选择正确的上下文。使用线程本地代理是实现此目的的常用方法。

9.2章中没有提到HttpServletRequest。

所以问题是:在并发方面将 HttpServletRequest 注入自定义 ContainRequestFilter 中是否安全?

我的意思是:

@Provider
@PreMatching
public class AuthenticationFilter implements ContainerRequestFilter {

   @Context private HttpServletRequest request;  

   @Override
   public void filter(ContainerRequestContext requestContext) throws IOException {
    // This is safe because every thread call the method with its requestContext
    String path = requestContext.getUriInfo().getPath(true);

    // Is this safe? The property request is injected by using @Context annotation (see above)
    String toReturn = (String)request.getAttribute(name);

    [...]
}

我在调试模式下对我的 IDE 进行了一些实证测试,使用两个不同的浏览器发送两个不同的并发请求,它似乎运行良好;我注意到过滤器的实例是一样的(它是一个单例),但是在这两种情况下注入的 HttpServletRequest 是不同的。

我什至读了这个帖子:How to access wicket session from Jersey-2 request filter?,看来我的测试得到了证实。

但我仍有疑问。

确认?

【问题讨论】:

    标签: jersey-2.0


    【解决方案1】:

    是的,它是安全的。要了解这个问题,您应该了解 范围 的工作原理。在任何处理范围(和注入)的框架中,该功能的实现方式类似。如果一个对象在单例范围内并且需要注入较小范围内的另一个对象,通常会注入该对象的代理。对对象进行调用时,实际上是对代理的调用。

    虽然规范可能没有特别提到HttpServletRequest,但大多数 JAX-RS 实现都支持这一点。特别是对于 Jersey,如果这是不可能的(意味着对象不可代理),那么您会在启动时收到一条错误消息,例如 “不在请求范围内”。原因是ContainerRequestFilter 是在应用启动时创建的,所有的注入也是在那个时候处理的。如果HttpServletRequest 不可代理,它将无法注入,因为在启动时,没有请求范围上下文。

    要确认它不是实际的HttpServletRequest 并且是代理,您可以记录request.getClass(),您会看到它确实是代理。

    如果您不熟悉此模式,可以查看this answer 了解其工作原理。

    另请参阅:

    【讨论】:

    • 嗨,peeskillet,你的回答非常清楚,你帮助我打破了我的疑虑。非常感谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-11
    • 1970-01-01
    • 1970-01-01
    • 2021-05-26
    • 2015-08-31
    • 2015-06-19
    相关资源
    最近更新 更多