我可以创建一个请求范围的对象并从任何地方访问它,并避免在JAX-RS中作为参数传递它吗?

时间:2016-04-01 12:15:32

标签: jax-rs cdi

假设我有一个使用一些HTTP头参数调用的Web服务/ REST资源。资源方法构建一个复杂的数据对象(当前是POJO)并最终将其返回给客户端(通过Gson作为JSON,但这并不重要)。

所以我有这个调用层次结构:

@Path(foo) ProjectResource @GET getProject()
-> new Project()
-> new List<Participant> which contains lots of new Participant()s
-> new Affiliation()

如果我希望Affiliation对象是例如根据标题参数填充英语或德语,我必须将其作为链中的参数传递。 我想避免这样做。也许这基本上是不可能的,但它感觉非常错误。所有这些对象只存在于请求中,因此从任何地方访问与请求相关的信息都不方便吗?

我希望我可以,例如定义一个初始化自身的CDI @RequestScoped对象(或由某个WebFilter填充),然后我可以在需要它的地方注入。

但很明显,这并不适用于POJO内部,而且我也无法从请求范围内的对象中获取头文件。

我已经阅读了很多有关EJB和JAX-RS上下文和CDI的SO问题/答案,但我无法理解它。

我期待太多了吗?传递参数确实是首选选项吗?

1 个答案:

答案 0 :(得分:4)

如果我理解你需要什么,你可以尝试以下方法(只是从我的头脑中写下这个解决方案,但它应该有效):

定义用于存储所需数据的类

定义一个用@RequestScoped注释的类,它将存储您需要的数据:

@RequestScoped
public class RequestMetadata {

    private Locale language;

    // Default constructor, getters and setters ommited
}

确保您使用@RequestScoped包中的javax.enterprise.context注释。

创建请求过滤器

创建ContainerRequestFilter以填充RequestMetadata

@Provider
@PreMatching
public class RequestMetadataFilter implements ContainerRequestFilter {

    @Inject
    private RequestMetadata requestMetadata;

    @Override
    public void filter(ContainerRequestContext requestContext) throws IOException {
        requestMetadata.setLanguage(requestContext.getLanguage());
    }
}

进行注射

然后,您最终可以使用@Inject

执行RequestMetadata的注入
@Stateless
public class Foo {

    @Inject
    private RequestMetadata requestMetadata;

    ...
}

请注意任何地方 太宽:注入将在容器管理的bean中运行,例如servlet,JAX-RS类,EJB和CDI例如,豆子。

您无法对自己创建的bean进行注入,也无法对JPA实体进行注入。