如何选择合适的bean范围? [英] How to choose the right bean scope?

查看:80
本文介绍了如何选择合适的bean范围?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I noticed that there are different bean scopes like:

@RequestScoped
@ViewScoped
@FlowScoped
@SessionScoped
@ApplicationScoped

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

What is the purpose of each? How do I choose a proper scope for my bean?

推荐答案

简介

它表示bean的作用域(生存期).如果您熟悉基本servlet Web应用程序的幕后"工作,这将更容易理解: @RequestScoped bean生存只要一个HTTP请求-响应周期(请注意,Ajax请求也算作一个HTTP请求). @ViewScoped bean的生存时间只要您正在通过回发与同一JSF视图进行交互,该回发调用了返回null/void的操作方法,而没有任何导航/重定向. @FlowScoped bean的生存时间只要您正在浏览流配置文件中注册的指定视图集合.一个 @SessionScoped bean的生存时间只要建立的HTTP会话. @ApplicationScoped bean的生存时间只要Web应用程序运行.请注意,CDI @Model本质上是定型@Named @RequestScoped的a>,因此适用相同的规则.

A @RequestScoped bean lives as long as a single HTTP request-response cycle (note that an Ajax request counts as a single HTTP request too). A @ViewScoped bean lives as long as you're interacting with the same JSF view by postbacks which call action methods returning null/void without any navigation/redirect. A @FlowScoped bean lives as long as you're navigating through the specified collection of views registered in the flow configuration file. A @SessionScoped bean lives as long as the established HTTP session. An @ApplicationScoped bean lives as long as the web application runs. Note that the CDI @Model is basically a stereotype for @Named @RequestScoped, so same rules apply.

选择哪个范围仅取决于bean所保存和表示的数据(状态).将@RequestScoped用于简单和非ajax表单/表示.将@ViewScoped用于启用了富Ajax的动态视图(基于ajax的验证,渲染,对话框等).将@FlowScoped用于收集分布在多个页面上的输入数据的向导"(问卷")模式.将@SessionScoped用于客户端特定的数据,例如登录的用户和用户首选项(语言等).将@ApplicationScoped用于应用程序范围的数据/常量,例如对于每个人都相同的下拉列表,或没有任何实例变量且仅具有方法的托管bean.

Which scope to choose depends solely on the data (the state) the bean holds and represents. Use @RequestScoped for simple and non-ajax forms/presentations. Use @ViewScoped for rich ajax-enabled dynamic views (ajaxbased validation, rendering, dialogs, etc). Use @FlowScoped for the "wizard" ("questionnaire") pattern of collecting input data spread over multiple pages. Use @SessionScoped for client specific data, such as the logged-in user and user preferences (language, etc). Use @ApplicationScoped for application wide data/constants, such as dropdown lists which are the same for everyone, or managed beans without any instance variables and having only methods.

滥用@ApplicationScoped bean来获取会话/视图/请求范围的数据将使其在所有用户之间共享,因此其他任何人都可以看到彼此的数据,这完全是错误的.将@SessionScoped bean用于视图/请求范围的数据将使其在单个浏览器会话中的所有选项卡/窗口之间共享,因此最终用户在选项卡之间切换后与每个视图进行交互时可能会遇到麻烦,这不利于用户体验.将@RequestScoped bean用作视图作用域数据将使视图作用域数据在每个单个(ajax)回发中都重新初始化为默认值,从而可能导致无法使用的表单(

Abusing an @ApplicationScoped bean for session/view/request scoped data would make it to be shared among all users, so anyone else can see each other's data which is just plain wrong. Abusing a @SessionScoped bean for view/request scoped data would make it to be shared among all tabs/windows in a single browser session, so the enduser may experience inconsitenties when interacting with every view after switching between tabs which is bad for user experience. Abusing a @RequestScoped bean for view scoped data would make view scoped data to be reinitialized to default on every single (ajax) postback, causing possibly non-working forms (see also points 4 and 5 here). Abusing a @ViewScoped bean for request, session or application scoped data, and abusing a @SessionScoped bean for application scoped data doesn't affect the client, but it unnecessarily occupies server memory and is plain inefficient.

请注意,除非您确实具有较低的内存占用空间并且希望完全变为无状态,否则不应根据性能的影响来选择范围.您只需要使用@RequestScoped bean并使用请求参数来保持客户端的状态.还要注意,当您只有一个JSF页面具有不同范围的数据时,将它们放在与数据范围相匹配的范围中的单独的支持bean中是完全有效的.如果是JSF管理的bean,则这些bean可以通过@ManagedProperty彼此访问;如果是使用CDI的bean,则可以通过@Inject彼此访问.

Note that the scope should rather not be chosen based on performance implications, unless you really have a low memory footprint and want to go completely stateless; you'd need to use exclusively @RequestScoped beans and fiddle with request parameters to maintain the client's state. Also note that when you have a single JSF page with differently scoped data, then it's perfectly valid to put them in separate backing beans in a scope matching the data's scope. The beans can just access each other via @ManagedProperty in case of JSF managed beans or @Inject in case of CDI managed beans.

  • Difference between View and Request scope in managed beans
  • Advantages of using JSF Faces Flow instead of the normal navigation system
  • Communication in JSF2 - Managed bean scopes

您的问题中未提及,但是(传统)JSF还支持 @CustomScoped @NoneScoped ,在现实世界中很少使用. @CustomScoped必须在更广泛的范围内引用自定义的Map<K, Bean>实现,该实现已覆盖了Map#put()和/或Map#get(),以便对Bean创建和/或销毁有更精细的控制.

It's not mentioned in your question, but (legacy) JSF also supports @CustomScoped and @NoneScoped, which are rarely used in real world. The @CustomScoped must refer a custom Map<K, Bean> implementation in some broader scope which has overridden Map#put() and/or Map#get() in order to have more fine grained control over bean creation and/or destroy.

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

The JSF @NoneScoped and CDI @Dependent basically lives as long as a single EL-evaluation on the bean. Imagine a login form with two input fields referring a bean property and a command button referring a bean action, thus with in total three EL expressions, then effectively three instances will be created. One with the username set, one with the password set and one on which the action is invoked. You normally want to use this scope only on beans which should live as long as the bean where it's being injected. So if a @NoneScoped or @Dependent is injected in a @SessionScoped, then it will live as long as the @SessionScoped bean.

  • Expire specific managed bean instance after time interval
  • what is none scope bean and when to use it?
  • What is the default Managed Bean Scope in a JSF 2 application?

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

As last, JSF also supports the flash scope. It is backed by a short living cookie which is associated with a data entry in the session scope. Before the redirect, a cookie will be set on the HTTP response with a value which is uniquely associated with the data entry in the session scope. After the redirect, the presence of the flash scope cookie will be checked and the data entry associated with the cookie will be removed from the session scope and be put in the request scope of the redirected request. Finally the cookie will be removed from the HTTP response. This way the redirected request has access to request scoped data which was been prepared in the initial request.

这实际上不能用作托管bean范围,即不存在@FlashScoped之类的东西. Flash范围只能通过 ExternalContext#getFlash() 在托管bean中,在#{flash}在EL中.

This is actually not available as a managed bean scope, i.e. there's no such thing as @FlashScoped. The flash scope is only available as a map via ExternalContext#getFlash() in managed beans and #{flash} in EL.

  • How to show faces message in the redirected page
  • Pass an object between @ViewScoped beans without using GET params
  • CDI missing @ViewScoped and @FlashScoped

这篇关于如何选择合适的bean范围?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆