我已经在这个问题上搜索了几个小时,没有eval。
WELD文档和CDI规范对所提供作用域的线程安全性非常清楚。
例如:应用范围-不安全
会话范围-不安全
请求作用域-安全,始终绑定到单个线程
对话范围-安全(由于WELD代理序列化来自多个请求线程的访问)
我在JSF 2.x定义的View Scope上找不到任何东西。
它与Conversation Scope大致处于相同的桶中,因为尽管它被绑定到单个视图/用户,但多个请求很可能并发地击中该范围。我不知道的是,JSF实现是否序列化了来自多个请求的对bean的访问。
有谁知道规范或Morraja/MyFaces实现可以澄清这一点吗?
正常使用的视图范围是线程安全的。它只能被一个浏览器窗口/选项卡使用。也就是说,它由在初始GET请求上设置的唯一隐藏输入字段进行键控。同一视图上的每个回发都将使用同一个视图作用域bean。浏览器本身已经"同步"了在同一窗口/选项卡中的回发请求。一个新的浏览器窗口/选项卡实际上是一个新的GET请求,因此将创建一个新的、完全独立的视图。
对于ajax回发,它们按规范排队。这在JSF 2规范的13.3.2章中提到过:
13.3.2 Ajax请求排队所有Ajax请求在被发送到服务器之前必须放入客户端请求队列服务器确保Ajax请求按照发送的顺序得到处理。在队列中等待的请求Longest是下一个要发送的请求。发送请求后,Ajax请求回调函数必须删除该请求从队列中退出(也称为退出队列)。如果请求成功完成,则必须将其从队列中删除。如果有一个错误,客户端必须被通知,但请求仍然必须从队列中删除,以便下一个请求可以发送。必须发送下一个请求(队列中最老的请求)。参考
jsf.ajax.request
关于Ajax请求队列的更多细节。
只有在使用PrimeFaces时,才能使用<p:ajax async="true">
禁用队列。当它与视图作用域bean结合使用时,必须重新考虑线程安全性,就像对会话作用域bean一样。
参见:
- @ applicationscope JSF托管bean的并发性
- 帮助我从并发视图理解JSF托管bean作用域
- 如何选择合适的bean scope?
ViewScoped
bean存储在为每个UIViewRoot
创建的"视图"Map
中。当JSF运行时处理两个并发请求时,通常不太可能为这些请求创建/恢复相同的UIViewRoot
实例,因为HTTP请求中的javax.faces.ViewState
表单参数用于确定是否应该恢复现有的UIViewRoot
实例(在回发时)。正如BalusC所指出的,两个不同的浏览器窗口将导致创建两个不同的视图作用域bean,因为两个浏览器选项卡的底层ViewStates参数是不同的(如果您发出两个不同的HTTP请求,并且浏览器使用每个请求的响应来显示单个选项卡,而不是使用缓存副本)。
javax.faces.ViewState
值,那么JSF运行时中(至少在Mojarra中)没有内在的机制来同步对UIViewRoot
和视图映射的访问。因此,视图作用域bean本质上不是线程安全的,也不能以线程安全的方式访问它们。您可以通过重放具有相同javax.faces.ViewState
值的请求来确认这一点,并观察容器/JVM在短时间内接收多个此类请求时的行为(导致多个线程并发访问相同UIViewRoot
实例的可能性)。