我有以下问题:
ContainerRequestFilter 是一个单例,但是阅读以下内容:
Jaxrs-2_0 Oracle 规范 http://download.oracle.com/otn-pub/jcp/jaxrs-2_0-fr-eval-spec/jsr339-jaxrs-2.0-final-spec.pdf?AuthParam=1447161642_e58ff98fc793e6bf6ef01aab8e594b20
在第 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 在这两种情况下是不同的。
我什至读过这个帖子:如何从 Jersey-2 请求过滤器访问 wicket 会话? https://stackoverflow.com/questions/19103853/how-to-access-wicket-session-from-jersey-2-request-filter看来我的测试得到了证实。
但我还是有疑问。
Confirm?
是的,它很安全。要理解这个问题,你应该理解如何scopes工作。在任何处理作用域(和注入)的框架中,该功能的实现方式都是类似的。如果一个对象位于单例范围内,并且需要注入较小范围内的另一个对象,通常会注入该对象的代理。当对对象进行调用时,实际上是对代理的调用。
尽管规范可能没有提及HttpServletRequest
具体来说,大多数 JAX-RS 实现都支持这一点。特别是对于 Jersey,如果这是不可能的(意味着该对象不可代理),那么您将在启动时收到一条错误消息,例如“不在请求范围内”。原因是,ContainerRequestFilter
在应用程序启动时创建,所有注入也在那时处理。如果HttpServletRequest
不可代理,它将无法注入,因为在启动时,没有请求范围上下文。
为了确认这不是真实的HttpServletRequest
并且是代理,您可以登录request.getClass()
,你会发现它确实是一个代理。
如果你不熟悉这个模式,你可以看看这个答案 https://stackoverflow.com/a/32937172/2587435了解它是如何工作的。
也可以看看:
- 使用 HK2 和 Jersey 将请求范围对象注入单例范围对象 http://paulsamsotha.blogspot.com/2015/12/injecting-request-scoped-objects-into.html
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)