简体   繁体   English

JSF 2.x @ViewScoped托管bean线程安全吗?

[英]Are JSF 2.x @ViewScoped managed beans thread safe?

I've been googling for a couple hours on this issue to no eval. 我已经在这个问题上搜索了两个小时,没有任何评价。

WELD docs and the CDI spec are pretty clear regarding thread safety of the scopes provided. 关于提供的范围的线程安全性,WELD文档和CDI规范非常清楚。

For example: 例如:

  • Application Scope - not safe 应用范围-不安全

  • Session Scope - not safe 会议范围-不安全

  • Request Scope - safe, always bound to a single thread 请求范围-安全,始终绑定到单个线程

  • Conversation Scope - safe (due to the WELD proxy serializing access from multiple request threads) 对话范围-安全(由于WELD代理对来自多个请求线程的访问进行了序列化)

I can't find anything on the View Scope defined by JSF 2.x. 我在JSF 2.x定义的View Scope上找不到任何内容。

It is in roughly the same bucket as the Conversation Scope in that it is very possible for multiple requests to hit the scope concurrently despite it being bound to a single view / user. 它与“对话范围”大致处于同一存储桶中,尽管有多个请求绑定到单个视图/用户,但很可能会同时命中该范围。 What I don't know is if the JSF implementation serializes access to the bean from multiple requests. 我不知道的是,JSF实现是否序列化了多个请求对Bean的访问。

Anyone have knowledge of the spec or of the Morraja/MyFaces implementations that could clear this up? 任何人都知道可以消除这种情况的规范或Morraja / MyFaces实现吗?

The view scope is with normal usage thread safe. 视图范围是正常使用线程安全的。 It can be used by only one browser window/tab. 只能由一个浏览器窗口/选项卡使用。 Namely, it's keyed by an unique hidden input field which is set on the initial GET request. 也就是说,它由在初始GET请求中设置的唯一隐藏输入字段作为键。 Every postback on the same view will use the one and same view scoped bean. 同一视图上的每个回发都将使用一个和同一视图作用域的Bean。 The browser itself already "synchronizes" postback requests in the same window/tab. 浏览器本身已经在同一窗口/选项卡中“同步”回发请求。 A new browser window/tab is effectively a new GET request and will therefore create a new and completely independent view. 新的浏览器窗口/选项卡实际上是新的GET请求,因此将创建一个新的且完全独立的视图。

As to ajax postbacks, they are by specification queued. 至于ajax回发,按规范它们被排队。 This is mentioned in chapter 13.3.2 of the JSF 2 specification : JSF 2规范的第13.3.2章提到了这一点:

13.3.2 Ajax Request Queueing 13.3.2 Ajax请求队列

All Ajax requests must be put into a client side request queue before they are sent to the server to ensure Ajax requests are processed in the order they are sent. 在将所有Ajax请求发送到服务器之前,必须将它们放入客户端请求队列中,以确保按发送顺序处理Ajax请求。 The request that has been waiting in the queue the longest is the next request to be sent. 在队列中等待时间最长的请求是下一个要发送的请求。 After a request is sent, the Ajax request callback function must remove the request from the queue (also known as dequeuing). 发送请求后,Ajax请求回调函数必须从队列中删除该请求(也称为出队)。 If the request completed successfully, it must be removed from the queue. 如果请求成功完成,则必须将其从队列中删除。 If there was an error, the client must be notified, but the request must still be removed from the queue so the next request can be sent. 如果发生错误,则必须通知客户端,但仍必须从队列中删除该请求,以便可以发送下一个请求。 The next request (the oldest request in the queue) must be sent. 必须发送下一个请求(队列中最旧的请求)。 Refer to the jsf.ajax.request JavaScript documentation for more specifics about the Ajax request queue. 有关Ajax请求队列的更多详细信息,请参阅jsf.ajax.request JavaScript文档。

Only when using PrimeFaces, queueing can be disabled with <p:ajax async="true"> . 仅在使用PrimeFaces时,可以使用<p:ajax async="true">禁用队列。 When using this in combination with view scoped beans, threadsafety must be reconsidered the same way as for session scoped beans. 与视图范围的Bean结合使用时,必须以与会话范围的Bean相同的方式重新考虑线程安全性。

See also: 也可以看看:

ViewScoped beans are stored in a "view" Map that is created for every UIViewRoot . ViewScoped bean存储在为每个UIViewRoot创建的“视图” Map中。 When two concurrent requests are processed by a JSF runtime, usually, it is unlikely that the same UIViewRoot instance is created/restored for these requests, as the javax.faces.ViewState form parameter in the HTTP request is used to determine whether an existing UIViewRoot instance should be restored or not (on postback). 当JSF运行时处理两个并发请求时,通常不太可能为这些请求创建/还原相同的UIViewRoot实例,因为HTTP请求中的javax.faces.ViewState表单参数用于确定是否存在现有的UIViewRoot实例是否应该恢复(回发时)。 As BalusC has indicated, two different browser windows will result in two different view scoped beans being created, as the underlying ViewStates parameters are different for both the browser tabs (if you are issuing two different HTTP requests and the browser is using the response of each to display the individual tabs, instead of using a cached copy). 正如BalusC指出的那样,两个不同的浏览器窗口将导致创建两个不同的视图范围的Bean,因为两个浏览器选项卡的基础ViewStates参数都不同(如果您发出两个不同的HTTP请求,并且浏览器正在使用每个响应以显示各个标签,而不是使用缓存的副本)。

The part about thread-safety however goes beyond browser tabs/windows. 但是,有关线程安全的部分超出了浏览器选项卡/窗口的范围。 There is no inherent mechanism within the JSF runtime (atleast within Mojarra) that will synchronize access to the UIViewRoot and the view map, if two HTTP requests (and hence, two threads) present the same javax.faces.ViewState value in the request to be processed by the container. 如果两个HTTP请求(因此,两个线程)在请求中呈现相同的javax.faces.ViewState值,则JSF运行时(在Mojarra中至少如此)内没有固有机制会同步对UIViewRoot和视图映射的访问。由容器处理。 Hence, view scoped beans are not threadsafe by nature, and neither are they accessed in a thread safe manner. 因此,视图作用域的bean本质上不是线程安全的,它们也不是以线程安全的方式访问的。 You could confirm this by replaying requests with the same javax.faces.ViewState values and observe the behavior of the container/JVM when multiple such requests are received by the container in a short duration (resulting in the possibility of concurrent access to the same UIViewRoot instance by multiple threads). 您可以通过使用相同的javax.faces.ViewState值重播请求来确认这一点,并在短时间内容器收到多个此类请求时观察容器/ JVM的行为(导致并发访问同一UIViewRoot的可能性)多个线程实例)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM