JAX-RS 2过滤器有哪些范围? [英] What scope do JAX-RS 2 filters have?

查看:125
本文介绍了JAX-RS 2过滤器有哪些范围?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用RestEasy 3.0.2,它是最早的JAX-RS 2实现之一,并在Tomcat 7中运行我的应用程序。我还通过WELD在我的应用程序中使用注入,WELD通过其CDI适配器与RestEasy集成。到目前为止一切正常。

I am using RestEasy 3.0.2 which is one of the first JAX-RS 2 implementations and run my application within a Tomcat 7. I also make use of injection in my application via WELD which is integrated with RestEasy via its CDI adaptor. Everything works fine so far.

现在,我编写了一个ContainerRequestFilter的实现,以在传入请求到达资源之前对其进行身份验证。 JAX-RS标准表示可以为每个资源以及使用@Provider注释注释的每个其他JAX-RS组件进行注入。

Now, I wrote an implementation of a ContainerRequestFilter to perform authentication of incoming requests before they hit a resource. The JAX-RS standard says that injection is possible for every resource and every other JAX-RS component that is annotated with a @Provider annotation.

这是一个简化版本的我的过滤器实现:

Here is a simplified version of my filter implementation:

@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

通常,此解决方案有效。正在注入组件并按预期处理请求。

In general, this solution works. The components are being injected and requests are being processed as expected.

但我仍然怀疑过滤器所处的范围。如果它是应用程序作用域,那么这显然会导致有趣的并发问题,这些问题在确定性测试中无法找到。

But I am still in doubt in which scope the filter is living. If it was application-scoped then this would obviously lead to "funny" concurrency issues that cannot be found with deterministic tests.

我已经查看了各种文档,指南和示例但是我发现没有使用过滤器注入过滤器或说过滤器范围。

I have looked into various documentation, guides and examples but I have found none that uses injection with filters or says something about the filter scope.

推荐答案

对于RestEasy,给出了答案在有关CDI集成的RestEasy文档中:

For RestEasy, the answer is given in the RestEasy documentation concerning CDI integration:


未明确定义范围的CDI bean默认为@Dependent
范围。这个伪范围意味着bean适应它注入的bean的
生命周期。正常范围(请求,
会话,应用程序)更适合JAX-RS组件,因为它们是b $ b明确指定组件的生命周期边界。因此,
resteasy-cdi模块以下列方式更改默认范围:

A CDI bean that does not explicitly define a scope is @Dependent scoped by default. This pseudo scope means that the bean adapts to the lifecycle of the bean it is injected into. Normal scopes (request, session, application) are more suitable for JAX-RS components as they designate component's lifecycle boundaries explicitly. Therefore, the resteasy-cdi module alters the default scoping in the following way:

如果JAX-RS根资源未明确定义范围,则是
绑定到请求范围。

If a JAX-RS root resource does not define a scope explicitly, it is bound to the Request scope.

如果JAX-RS Provider或javax.ws.rs.Application子类未明确定义范围
,则绑定到应用程序范围。

因此,使用@Provider注释的JAX-RS过滤器是@ApplicationScoped。

Therefor JAX-RS filters annotated with @Provider are @ApplicationScoped.

文档还说明JAX-RS提供程序可以通过为其添加适当的注释来与任何范围相关联。因此,一般情况下,可以自定义JAX-RS过滤器的范围。

The documentation also says that a JAX-RS provider can be associated with any scope by putting the proper annotation to it. So in general, the scope of a JAX-RS filter can be customized.

重要的是要注意将@RequestScoped对象注入@ApplicationScoped过滤器是安全的。这是因为CDI不会将实际对象的引用注入代理。当在代理上调用方法时,对象的单独实例将用于幕后的每个请求。

It is important to notice that it is safe to inject @RequestScoped objects into an @ApplicationScoped filter. This is, because CDI does not inject a reference to the actual object but to a proxy. When a method is invoked on the proxy, a separate instance of the object will be used for each request behind the scenes.

这里相应的 WELD文档


4.9。客户端代理

4.9. Client proxies

注入bean的客户端通常不持有对
a bean实例的直接引用,除非bean是依赖对象(范围
@Dependent)。

Clients of an injected bean do not usually hold a direct reference to a bean instance, unless the bean is a dependent object (scope @Dependent).

想象一下,绑定到应用程序范围的bean持有对绑定到请求范围的bean的直接
引用。应用程序范围的
bean在许多不同的请求之间共享。但是,每个请求
应该看到请求范围bean的不同实例 - 当前
一个!

Imagine that a bean bound to the application scope held a direct reference to a bean bound to the request scope. The application-scoped bean is shared between many different requests. However, each request should see a different instance of the request scoped bean—the current one!

...

因此,除非bean具有默认范围@Dependent,否则
容器必须通过
代理对象间接地对bean进行所有注入引用。此客户端代理负责确保接收方法调用的
bean实例是
与当前上下文关联的实例。客户端代理还允许绑定到上下文的
bean(例如会话上下文)序列化为
到磁盘而不递归序列化其他注入的bean。

Therefore, unless a bean has the default scope @Dependent, the container must indirect all injected references to the bean through a proxy object. This client proxy is responsible for ensuring that the bean instance that receives a method invocation is the instance that is associated with the current context. The client proxy also allows beans bound to contexts such as the session context to be serialized to disk without recursively serializing other injected beans.

我使用以下代码来验证这一点(假设 entityManager 在示例中生成为@RequestScoped):

I used the following code to validate this (assume that the entityManager is produced as @RequestScoped in the example):

@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());
    }
} 

这给出了会话的不同哈希值,用于过滤器处理的每个请求。所以理论和实践在这里匹配。

This gives a different hash value of session for every request processed by the filter. So theory and practice match here.

这篇关于JAX-RS 2过滤器有哪些范围?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆