我正在使用RestEasy 3.0.2,这是第一个JAX-RS 2实现之一,并在Tomcat 7中运行我的应用程序。我还通过WELD在我的应用程序中使用注入,WELD通过其CDI适配器与RestEasy集成。到目前为止一切正常。
现在,我编写了一个ContainerRequestFilter的实现,以在传入请求到达资源之前对其进行身份验证。 JAX-RS标准表示可以为每个资源以及使用@Provider注释注释的所有其他JAX-RS组件进行注入。
以下是我的过滤器实现的简化版本:
@Provider
@Priority(Priorities.AUTHENTICATION)
public class AuthenticationFilter implements ContainerRequestFilter {
@Inject
AuthenticationProvider authenticationProvider;
@Override
public void filter(ContainerRequestContext requestContext) throws IOException {
authenticationProvider.authenticate(requestContext);
}
}
注意: AuthenticationProvider 是 @RequestScoped 。
通常,此解决方案有效。正在注入组件并按预期处理请求。
但我仍然怀疑过滤器的生活范围。如果它是应用程序作用域,那么这显然会导致“有趣”的并发问题,这些问题在确定性测试中无法找到。
我已经查看了各种文档,指南和示例,但我发现没有使用过滤器注入或者说过滤器范围。
答案 0 :(得分:5)
对于RestEasy,答案在RestEasy documentation concerning CDI integration:
中给出未明确定义范围的CDI bean是@Dependent 默认情况下作用域。这个伪范围意味着bean适应了 注入的bean的生命周期。正常范围(请求, 会话,应用程序)更适合JAX-RS组件 明确指定组件的生命周期边界。因此, resteasy-cdi模块以下列方式更改默认范围:
如果JAX-RS根资源未明确定义范围,则为 绑定到请求范围。
如果JAX-RS Provider或javax.ws.rs.Application子类未定义范围 显式地,它绑定到应用程序范围。
因此,使用@Provider注释的JAX-RS过滤器是@ApplicationScoped。
该文档还说,JAX-RS提供程序可以通过为其添加适当的注释来与任何范围相关联。因此,一般来说,JAX-RS过滤器的范围可以定制。
重要的是要注意将@RequestScoped对象注入@ApplicationScoped过滤器是安全的。这是因为CDI不会将实际对象的引用注入代理。在代理上调用方法时,对象的单独实例将用于幕后的每个请求。
4.9。客户代理
注入bean的客户端通常不直接引用 bean实例,除非bean是依赖对象(范围 @Dependent)。
想象一下绑定到应用程序范围的bean是直接的 引用绑定到请求范围的bean。应用范围 bean在许多不同的请求之间共享。但是,每个请求 应该看到请求范围bean的不同实例 - 当前 一个!
...
因此,除非bean具有默认范围@Dependent,否则 容器必须通过a间接所有注入bean的引用 代理对象。此客户端代理负责确保 接收方法调用的bean实例就是实例 与当前上下文相关联。客户端代理也允许 绑定到上下文的bean,例如要序列化的会话上下文 到磁盘而不递归序列化其他注入的bean。
我使用以下代码来验证这一点(假设 entityManager 在示例中生成为@RequestScoped):
@Provider
public class OtherTestFilter implements ContainerRequestFilter {
@Inject
EntityManager entityManager;
@Override
public void filter(ContainerRequestContext requestContext) throws IOException {
Session session = (Session) entityManager.getDelegate();
System.out.println(session.hashCode());
}
}
这为过滤器处理的每个请求提供了 session 的不同哈希值。所以理论和实践在这里相配。
答案 1 :(得分:0)
它的定义方式,看起来像是DependentScoped。唯一的另一种可能性是沉默的RequestScoped,但这不太可能。
答案 2 :(得分:0)
JAX-RS 2过滤器有什么作用范围?
过滤器之类的提供程序默认为单个。
摘自Application
文档:
资源类实例的默认生命周期是每个请求。提供程序(直接注册或通过功能注册)的默认生命周期为单例。
默认情况下,为每个JAX-RS应用程序实例化每个提供程序类的单个实例。首先,调用构造函数,然后注入所有请求的依赖项,然后可以多次(同时)调用适当的提供者方法,最后使该对象可用于垃圾回收。
JAX-RS规范还提到了有关CDI集成的以下内容:
提供者和
Application
子类必须为单例或使用应用程序范围。