我一直在谷歌搜索这个问题几个小时没有评估。
WELD文档和CDI规范对于所提供范围的线程安全性非常清楚。
例如:
申请范围 - 不安全
会话范围 - 不安全
请求范围 - 安全,始终绑定到单个线程
会话范围 - 安全(由于WELD代理序列化来自多个请求线程的访问)
我在JSF 2.x定义的View Scope上找不到任何内容。
它与对话范围大致相同,因为尽管绑定到单个视图/用户,但多个请求很可能同时命中范围。我不知道的是JSF实现是否从多个请求序列化对bean的访问。
任何人都知道规格或Morraja / MyFaces实施可以解决这个问题吗?
答案 0 :(得分:17)
视图范围与正常使用线程安全。它只能由一个浏览器窗口/选项卡使用。也就是说,它由在初始GET请求上设置的唯一隐藏输入字段键控。同一视图上的每个回发都将使用同一个视图范围的bean。浏览器本身已在同一窗口/选项卡中“同步”回发请求。新的浏览器窗口/选项卡实际上是一个新的GET请求,因此将创建一个新的完全独立的视图。
关于ajax回发,它们按规范排队。这在JSF 2 specification的第13.3.2节中提到:
13.3.2 Ajax请求队列
在将所有Ajax请求发送到客户端请求队列之前,必须将它们放入客户端请求队列中 服务器,以确保Ajax请求按发送顺序处理。已在队列中等待的请求 最长的是下一个要发送的请求。发送请求后,Ajax请求回调函数必须删除该请求 从队列(也称为队列)。如果请求成功完成,则必须将其从队列中删除。如果 出现错误,必须通知客户端,但仍必须从队列中删除请求,以便下一个请求 可以发送。必须发送下一个请求(队列中最早的请求)。请参阅
jsf.ajax.request
有关Ajax请求队列的更多细节的JavaScript文档。
仅在使用PrimeFaces时,可以使用<p:ajax async="true">
禁用排队。将此与视图范围bean结合使用时,必须以与会话范围bean相同的方式重新考虑threadsafety。
答案 1 :(得分:3)
ViewScoped
个bean存储在为"view" Map
创建的UIViewRoot
中。当JSF运行时处理两个并发请求时,通常不会为这些请求创建/恢复相同的UIViewRoot
实例,因为HTTP请求中的javax.faces.ViewState
表单参数用于确定是否应恢复现有的UIViewRoot
实例(在回发时)。正如BalusC指出的那样,两个不同的浏览器窗口将导致创建两个不同的视图范围bean,因为两个浏览器选项卡的底层ViewStates参数不同(如果您发出两个不同的HTTP请求,并且浏览器使用每个浏览器的响应)显示各个选项卡,而不是使用缓存副本。)
关于线程安全的部分不仅限于浏览器选项卡/窗口。如果两个HTTP请求(因此两个线程)呈现相同的UIViewRoot
值,则JSF运行时(至少在Mojarra中)内部没有固有的机制可以同步对javax.faces.ViewState
和视图的访问。在容器处理的请求中。因此,视图范围内的bean本质上不是线程安全的,也不是以线程安全的方式访问它们。您可以通过重播具有相同javax.faces.ViewState
值的请求来确认这一点,并在容器在短时间内收到多个此类请求时观察容器/ JVM的行为(导致可能同时访问同一{多个线程的{1}}实例。)