@WebListener
public class AllRequestsWebListener implements ServletRequestListener {
@Inject HttpRequestProducer producer;
public void requestInitialized(ServletRequestEvent sre) {
producer.requestInitialized(sre);
}
}
...
@RequestScoped
public class HttpRequestProducer {
...
}
我不知道如何将request-bean注入方法参数,因此我可以猜测,当Request-bean注入为threadLocal时它将正常工作。有人能解释一下它是如何以线程安全的方式实现的吗?
答案 0 :(得分:1)
你在bean中注入的是代表真实交易的代理。代理将始终将调用转发给正确的bean
答案 1 :(得分:0)
基于直觉的回答
我认为它是线程安全的,因为请求范围是线程安全的(会话及以上不是,因为用户可以打开多个浏览器会话并使用相同的会话ID)
我测试了它,虽然它是经验证据,但注入的HttpRequestProducer
每个请求获得一个新实例。
请注意,requestInitialized
和requestDestroyed
可以(实际上是)不同的线程,因此如果您打算在两种方法上使用相同的注入对象,我将进一步调查。
规范支持的答案
困难的部分是在规范中找到这个主张的确凿证据。
我查看了CDI规范并且无法快速找到确凿的证据证明@RequestScoped对象是线程安全的(例如使用线程本地)但是我假设@RequestScoped bean使用与Java中的scoped bean相同的范围EE 5 :(见here)
在那里,这个条款很有意思:
在多线程中控制对共享资源的并发访问 服务器,可以访问共享资源 同时。除了范围对象属性,共享资源 包括内存中的数据(例如实例或类变量)和 外部对象,如文件,数据库连接和网络 连接。
在几种情况下可能会出现并发访问:
多个Web组件访问存储在Web上下文中的对象。
多个Web组件访问存储在会话中的对象。
访问实例变量的Web组件中的多个线程。 Web容器通常会创建一个线程来处理每个请求。 如果要确保servlet实例仅处理一个请求 一次,servlet可以实现SingleThreadModel接口。如果 一个servlet实现了这个接口,你保证没有两个 线程将在servlet的服务方法中并发执行。一个 Web容器可以通过同步访问来实现此保证 servlet的单个实例,或者维护一个Web池 组件实例并将每个新请求分派给一个免费的 实例。此接口不会阻止同步问题 Web组件访问共享资源的结果,例如 静态类变量或外部对象。另外,Servlet 2.4规范不推荐使用SingleThreadModel接口。
所以从理论上讲,似乎对象本身每个请求线程都有一个实例,但是我找不到任何支持这个实例的确凿证据。