区分不同类型的JSF托管Bean

46

我最近读了Neil Griffin的这篇文章Making Distinctions Between Different Kinds of JSF Managed-Beans,这让我思考起我自己应用程序中不同bean之间的区别。简要总结如下:

  • Model Managed-Bean: 这种类型的托管bean参与MVC设计模式中的“Model”关注点。当您看到“model”一词时,请思考数据。JSF模型bean应该是遵循JavaBean设计模式的POJO,具有封装属性的getter / setter。

  • Backing Managed-Bean: 这种类型的托管bean参与MVC设计模式中的“View”关注点。backing-bean的目的是支持UI逻辑,并且与JSF视图或Facelet组合中的JSF表单具有1:1的关系。虽然它通常具有与关联的getter / setter的JavaBean样式属性,但这些是视图的属性,而不是底层应用程序数据模型的属性。JSF后备bean还可以具有JSF actionListener和valueChangeListener方法。

  • Controller Managed-Bean: 这种类型的托管bean参与MVC设计模式中的“Controller”关注点。控制器bean的目的是执行某种业务逻辑并向JSF navigation-handler返回导航结果。JSF控制器bean通常具有JSF动作方法(而不是actionListener方法)。

  • Support Managed-Bean: 这种类型的bean在MVC设计模式中“View”关注点中支持一个或多个视图。典型用例是向显示在多个JSF视图中的JSF h: selectOneMenu下拉列表提供ArrayList。如果下拉列表中的数据特定于用户,则将保留bean会话范围。

  • Utility Managed-Bean: 此类型的bean提供某种类型的辅助功能,如格式化日期或转换字符串。它们通常没有与视图相关的属性,但可以具有静态方法。

为一个或多个JSF视图添加“实用”函数。一个很好的例子可能是文件上传bean,可以在多个Web应用程序中重复使用。

这对我来说很有意义,过去几个小时我一直在重构代码,并得出了以下关于用户登录的方案:

AuthenticationController 是一个控制器托管bean的示例。它是请求范围的,具有两个getter和setter用于设置用户名和密码,以及两个导航方法 authenticatelogout,在成功登录时将用户导航到其私人区域,或在注销时返回主页。

UserBean 是支持托管bean的示例。它是会话范围的,并且具有一个User类的实例(当您没有经过身份验证时为null)和一个getter和setter,没有其他内容。

AuthenticationController 将此用户作为托管属性(@ManagedProperty(value = "#{userController.user} private User user;)。在成功认证后,AuthenticationController会将托管属性设置为实际用户实例,该实例具有用于登录的相应用户名。

任何新的bean也可以将用户作为托管属性获取,并提取他们所需的数据,例如组成员身份,如果User类具有包含组名的列表。

这种方式是关注点分离的正确方式吗?

1个回答

90

这是一个非常主观的问题。我个人不同意这篇文章,并且认为它给新手提供了非常糟糕的建议。


模型托管Bean:这种类型的托管Bean参与MVC设计模式中的“模型”关注点。当您看到“模型”一词时,请考虑数据。JSF模型bean应该是一个POJO,遵循JavaBean设计模式,具有封装属性的getter / setter。
我绝对不会将其称为托管bean,只需将其作为@ManagedBean的属性即可。例如DTO或JPA@Entity。

Backing Managed-Bean:这种类型的托管bean参与MVC设计模式中的“View”关注点。支持UI逻辑是后备bean的目的,并且与JSF视图或Facelet组合中的JSF表单具有1::1关系。虽然它通常具有JavaBean风格的属性和相关的getter/setter,但这些是视图的属性--而不是底层应用程序数据模型的属性。JSF后备bean也可以具有JSF actionListener和valueChangeListener方法。

这样做会使您在托管bean中重复并映射实体的属性。对我来说毫无意义。正如所说,只需将实体作为托管bean的属性,并让输入字段直接引用它,如#{authenticator.user.name},而不是#{authenticator.username}


Controller Managed-Bean: 这种类型的Managed-Bean参与MVC设计模式中的"控制器"关注点。控制器bean的目的是执行某种业务逻辑并将导航结果返回给JSF导航处理程序。JSF控制器bean通常具有JSF操作方法(而不是actionListener方法)。

这基本上描述了@RequestScoped/@ViewScoped @ManagedBean类。是否允许事件监听器方法取决于它们是否特定于绑定到bean的视图以及/或者它们是否依赖于bean的状态来完成工作。如果是,则应该放在bean中。否则,它们应该是任何FacesListener接口的独立实现,但绝对不能是托管bean。


支持托管Bean:这种类型的Bean“支持”MVC设计模式中“视图”关注点中的一个或多个视图。典型用例是为JSF h:selectOneMenu下拉列表提供ArrayList,该下拉列表出现在多个JSF视图中。如果下拉列表中的数据特定于用户,则应将Bean保留在会话范围内。

好的。对于应用程序范围的数据,例如下拉列表,只需使用@ApplicationScoped bean,对于会话范围的数据,例如已登录用户及其首选项,只需使用@SessionScoped bean。


Utility Managed-Bean:这种bean为一个或多个JSF视图提供某种“实用”功能。一个很好的例子是可以在多个Web应用程序中重复使用的FileUpload bean。

这对我来说没有太多意义。Backing beans通常与单个视图相关联。这听起来太像ActionListener实现,可由<f:actionListener>在命令组件中使用。绝对不是托管的bean。

有关正确方法的启动示例,请参见:


3
谢谢BalusC!我想我需要摆脱固定的项目组织规则的观念,更加务实一些,不要纠结于这样的文章并强迫自己遵守。 - Laurens
8
+1 我无法给这个答案点赞得够多!我读了那篇文章一百遍,花了一些时间试图按照它的建议去做,但最终放弃了,因为重复太多的事情对我来说没有意义... - Elias Dorneles
3
谢谢BalusC。最初这篇文章对我来说很有意义,因为我是JSF新手,但在尝试了一些bean操作后,您的更新更加易懂。 - GeraldScott
1
今天我们遇到了这个问题,@BalusC,我在谷歌上搜索解释时发现了你的答案。我不同意文章的观点,但实际上我也无法理解你的观点。在我看来,ManagedBeans处于视图和模型之间,而FacesServlet是控制器。但我很想知道你的意见。 - Jaumzera

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接