Jersey 2:过滤器和@Context 注入
Jersey 2: filters and @Context injections
我有以下问题:
ContainerRequestFilter 是一个单例,但是读到这里:
在第 9.2 章中,他们说:
Context is specific to a particular request but instances of certain JAX-RS components (providers and resource classes with a lifecycle other than per-request) may need to support multiple concurrent requests. When injecting an instance of one of the types listed in Section 9.2, the instance supplied MUST be capable of selecting the correct context for a particular request. Use of a thread-local proxy is a common way to achieve this.
在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? 看来我的测试得到了确认。
但我还是有疑问
确认?
是的,它很安全。要理解这个问题,您应该理解 scopes 是如何工作的。在任何处理范围(和注入)的框架中,该功能的实现都是类似的。如果一个对象在单例范围内,而另一个在较小范围内的对象需要注入,通常会注入该对象的代理。当对对象进行调用时,实际上是对代理的调用。
虽然规范可能没有具体提到 HttpServletRequest
,但大多数 JAX-RS 实现都支持它。特别是对于 Jersey,如果这是不可能的(意味着对象不可代理),那么您将在启动时收到一条错误消息,如 "not within a request scope"。原因是 ContainerRequestFilter
是在应用程序启动时创建的,所有的注入也是在那个时候处理的。如果 HttpServletRequest
不可代理,它将无法注入,因为在启动时,没有请求范围上下文。
要确认它不是实际的HttpServletRequest
并且是代理,您可以登录request.getClass()
,您会看到它确实是代理。
如果您不熟悉此模式,可以查看 this answer 了解其工作原理。
另请参阅:
我有以下问题:
ContainerRequestFilter 是一个单例,但是读到这里:
在第 9.2 章中,他们说:
Context is specific to a particular request but instances of certain JAX-RS components (providers and resource classes with a lifecycle other than per-request) may need to support multiple concurrent requests. When injecting an instance of one of the types listed in Section 9.2, the instance supplied MUST be capable of selecting the correct context for a particular request. Use of a thread-local proxy is a common way to achieve this.
在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? 看来我的测试得到了确认。
但我还是有疑问
确认?
是的,它很安全。要理解这个问题,您应该理解 scopes 是如何工作的。在任何处理范围(和注入)的框架中,该功能的实现都是类似的。如果一个对象在单例范围内,而另一个在较小范围内的对象需要注入,通常会注入该对象的代理。当对对象进行调用时,实际上是对代理的调用。
虽然规范可能没有具体提到 HttpServletRequest
,但大多数 JAX-RS 实现都支持它。特别是对于 Jersey,如果这是不可能的(意味着对象不可代理),那么您将在启动时收到一条错误消息,如 "not within a request scope"。原因是 ContainerRequestFilter
是在应用程序启动时创建的,所有的注入也是在那个时候处理的。如果 HttpServletRequest
不可代理,它将无法注入,因为在启动时,没有请求范围上下文。
要确认它不是实际的HttpServletRequest
并且是代理,您可以登录request.getClass()
,您会看到它确实是代理。
如果您不熟悉此模式,可以查看 this answer 了解其工作原理。
另请参阅: