19

我已经在这个问题上搜索了几个小时没有评估。

WELD 文档和 CDI 规范对所提供范围的线程安全性非常清楚。

例如:

  • 应用范围 - 不安全

  • 会话范围 - 不安全

  • 请求范围 - 安全,始终绑定到单个线程

  • 对话范围 - 安全(由于 WELD 代理序列化来自多个请求线程的访问)

我在 JSF 2.x 定义的视图范围内找不到任何东西。

它与对话范围大致在同一个桶中,因为尽管它绑定到单个视图/用户,但多个请求很有可能同时到达范围。我不知道 JSF 实现是否序列化了从多个请求对 bean 的访问。

任何人都知道规范或 Morraja/MyFaces 实现可以解决这个问题吗?

4

2 回答 2

19

视图范围是正常使用线程安全的。它只能由一个浏览器窗口/选项卡使用。也就是说,它由一个在初始 GET 请求中设置的唯一隐藏输入字段作为键控。同一视图上的每个回发都将使用同一个视图范围 bean。浏览器本身已经在同一窗口/选项卡中“同步”回发请求。新的浏览器窗口/选项卡实际上是一个新的 GET 请求,因此将创建一个新的且完全独立的视图。

至于 ajax 回发,它们按规范排队。JSF 2 规范的第 13.3.2 章提到了这一点:

13.3.2 Ajax 请求队列

所有 Ajax 请求在发送到服务器之前都必须放入客户端请求队列,以确保 Ajax 请求按照发送顺序进行处理。在队列中等待时间最长的请求是下一个要发送的请求。发送请求后,Ajax 请求回调函数必须将请求从队列中移除(也称为出队)。如果请求成功完成,则必须将其从队列中删除。如果出现错误,必须通知客户端,但仍必须从队列中删除请求,以便可以发送下一个请求。必须发送下一个请求(队列中最早的请求)。有关 Ajax 请求队列的更多详细信息,请参阅jsf.ajax.request JavaScript 文档。

只有在使用 PrimeFaces 时,才能使用 禁用排队<p:ajax async="true">。当将它与视图范围的 bean 结合使用时,必须重新考虑线程安全,方法与会话范围的 bean 相同。

也可以看看:

于 2011-09-14T03:21:15.290 回答
4

ViewScopedbean 存储在为每个. MapUIViewRoot当 JSF 运行时处理两个并发请求时,通常不太可能UIViewRoot为这些请求创建/恢复同一个实例,因为 HTTP 请求中的表单参数用于确定是否应该恢复javax.faces.ViewState现有实例(UIViewRoot回发)。正如 BalusC 所指出的,两个不同的浏览器窗口将导致创建两个不同的视图范围 bean,因为两个浏览器选项卡的底层 ViewStates 参数不同(如果您发出两个不同的 HTTP 请求并且浏览器正在使用每个显示各个选项卡,而不是使用缓存副本)。

然而,关于线程安全的部分超出了浏览器选项卡/窗口。UIViewRoot如果两个 HTTP 请求(因此,两个线程)javax.faces.ViewState在要由容器处理的请求中呈现相同的值,则 JSF 运行时(至少在 Mojarra 中)没有内在的机制来同步对视图和视图映射的访问。因此,视图范围的 bean 本质上不是线程安全的,它们也不是以线程安全的方式访问的。您可以通过重放具有相同javax.faces.ViewState值的请求来确认这一点,并观察容器在短时间内收到多个此类请求时容器/JVM 的行为(导致UIViewRoot多个线程并发访问同一实例的可能性)。

于 2011-09-14T04:27:02.807 回答