一尘不染

如何选择合适的bean范围?

jsf

我注意到有不同的bean作用域,例如:

@RequestScoped
@ViewScoped
@FlowScoped
@SessionScoped
@ApplicationScoped

每个的目的是什么?如何为我的bean选择合适的范围?


阅读 331

收藏
2020-09-30

共1个答案

一尘不染

介绍
它表示bean的范围(生存期)。如果您熟悉基本Servlet Web应用程序的“幕后”工作,这将更容易理解:Servlet如何工作?实例化,会话,共享变量和多线程。

@Request/View/Flow/Session/ApplicationScoped

一个@RequestScopedbean的生存时间只有一个HTTP请求-响应周期(请注意,Ajax请求也算作一个HTTP请求)。一个@ViewScopedbean的生命,只要你与通过调用操作方法返回回送相同的JSF视图交互null/void无任何导航/重定向。一个@FlowScopedbean的生命,只要你通过的流量配置文件中注册的视图指定的集合导航。一个@SessionScopedbean的生命,只要建立HTTP会话。一@ApplicationScoped豆住,只要运行Web应用程序。请注意,CDI@Model基本上是一个刻板的@Named @RequestScoped,所以规则也同样适用。

选择哪个范围仅取决于bean持有和表示的数据(状态)。使用@RequestScoped简单和非Ajax表格/演示。使用@ViewScoped了丰富的支持Ajax的动态视图(ajaxbased验证,渲染,对话框等)。使用@FlowScoped的“向导”(“问卷”)在多个页面收集的输入数据传播的模式。使用@SessionScoped客户端的具体数据,如登录的用户和用户偏好(语言等)。使用@ApplicationScoped应用程序范围内的数据/常量,比如下拉列表,是适合每一个人,或管理的bean没有任何实例变量和仅有的方法相同。

@ApplicationScopedbean用于会话/视图/请求范围的数据会使其在所有用户之间共享,因此其他任何人都可以看到彼此的数据,这完全是错误的。将@SessionScopedbean用于视图/请求范围的数据会使其在单个浏览器会话中的所有选项卡/窗口之间共享,因此最终用户在选项卡之间切换后与每个视图进行交互时可能会遇到麻烦,这不利于用户体验。将@RequestScopedbean用作视图作用域数据将使视图作用域数据在每次单次(ajax)回发时都重新初始化为默认值,从而可能导致无法正常工作的表单(另请参见第4点和第5点)。滥用@ViewScopedbean获取请求,会话或应用程序范围的数据,并滥用@SessionScoped 用于应用程序范围的数据的bean不会影响客户端,但是不必要地占用了服务器内存,并且效率很低。

请注意,除非您确实具有较低的内存占用空间并希望完全无状态,否则不应根据性能的影响来选择范围。您将需要专门使用@RequestScopedbean并使用请求参数来维护客户端的状态。还要注意,当您只有一个JSF页面包含范围不同的数据时,将它们放在与数据范围相匹配的范围内的单独的支持bean中是完全有效的。@ManagedProperty在JSF托管Bean或@InjectCDI托管Bean的情况下,Bean只能通过彼此访问。

@CustomScoped/NoneScoped/Dependent

您的问题中没有提到它,但是(传统)JSF还支持@CustomScoped和@NoneScoped,这在现实世界中很少使用。在@CustomScoped必须引用定制的Map,其中有一些重载更大范围的实现Map#put()和/或Map#get()以有超过bean创建更为精细的控制和/或破坏。

只要在bean上进行一次EL评估,JSF@NoneScoped和CDI@Dependent基本上就可以存在。想象一下一个登录表单,其中有两个输入字段引用一个bean属性,一个命令按钮引用一个bean操作,因此总共有三个EL表达式,那么实际上将创建三个实例。一种设置了用户名,一种设置了密码,另一种调用了操作。通常,您只想在应与注入的bean一样长的bean上使用此作用域。因此,如果将@NoneScoped或@Dependent注入到中@SessionScoped,则它将与@SessionScopedbean一样长。

闪光灯范围

最后,JSF还支持Flash作用域。它由一个与会话范围内的数据条目相关联的短期Cookie支持。重定向之前,将在HTTP响应上设置一个cookie,该cookie的值与会话范围内的数据条目唯一关联。重定向之后,将检查Flash作用域cookie的存在,并将与cookie关联的数据条目从会话作用域中删除,并将其放入重定向请求的请求作用域中。最后,cookie将从HTTP响应中删除。这样,重定向的请求可以访问在初始请求中准备的请求范围数据。

实际上,这不能作为托管bean范围使用,即不存在@FlashScoped。闪存作用域仅通过ExternalContext#getFlash()托管Bean和#{flash}EL中的地

2020-09-30