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

Ant*_*s42 0 jax-rs cdi

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

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

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

如果我想Affiliation根据标题参数以英语或德语填充对象,则必须将其作为参数传递给链下。我想避免这样做。也许这从根本上讲是不可能的,但是感觉太不对了。所有这些对象仅存在于请求中,因此能够从任何地方访问与请求相关的信息是否方便?

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

但是显然,这在POJO内部是行不通的,而且我也很难从请求范围的对象内部获取标头。

我已经阅读了许多关于EJB,JAX-RS上下文和CDI的SO问题/答案,但是我无法解决。

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

cas*_*lin 5

如果我了解您的需求,则可以尝试以下方法(只是从头开始编写此解决方案,但它应该可以工作):

定义一个类来存储所需的数据

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

@RequestScoped
public class RequestMetadata {

    private Locale language;

    // Default constructor, getters and setters ommited
}
Run Code Online (Sandbox Code Playgroud)

确保您使用的@RequestScopedjavax.enterprise.context包装中的注释。

创建一个请求过滤器

创建一个ContainerRequestFilter以填充RequestMetadata

@RequestScoped
public class RequestMetadata {

    private Locale language;

    // Default constructor, getters and setters ommited
}
Run Code Online (Sandbox Code Playgroud)

进行注射

然后,您最终可以执行RequestMetadatausing 的注入@Inject

@Provider
@PreMatching
public class RequestMetadataFilter implements ContainerRequestFilter {

    @Inject
    private RequestMetadata requestMetadata;

    @Override
    public void filter(ContainerRequestContext requestContext) throws IOException {
        requestMetadata.setLanguage(requestContext.getLanguage());
    }
}
Run Code Online (Sandbox Code Playgroud)

请注意,任何地方太广泛了:注入将对容器管理的bean起作用,例如servlet,JAX-RS类,EJB和CDI bean。

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