46

我最近阅读了 Neil Griffin 的这篇文章区分不同种类的 JSF Managed-Beans,它让我思考了我自己的应用程序中不同 bean 之间的区别。快速总结要点:

  • Model Managed-Bean:这种类型的 managed-bean 参与了 MVC 设计模式的“模型”关注点。当你看到“模型”这个词时——想想 DATA。JSF 模型bean 应该是遵循JavaBean 设计模式的POJO,其中getter/setter 封装了属性。

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

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

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

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

这对我来说很有意义,在过去的几个小时里,我一直在重构我的代码,并就用户登录提出了以下建议:

AuthenticationController是 Controller Managed-Bean 的一个示例。它是请求范围的,具有两个用于设置用户名和密码的 getter 和 setter,以及两个导航方法,authenticate以及logout,在成功登录时将用户导航到他们的私人区域,或者在注销时导航到主页。

UserBean是 Support Managed-Bean 的一个示例。它是会话范围的,并具有一个带有 getter 和 setter 的类实例User(当您未经过身份验证时,它会为 null),仅此而已。

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

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

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

4

1 回答 1

90

这是一个非常主观的问题。我个人不同意那篇文章,并发现它给初学者提供了非常糟糕的建议。


Model Managed-Bean:这种类型的 managed-bean 参与了 MVC 设计模式的“模型”关注点。当你看到“模型”这个词时——想想 DATA。JSF 模型bean 应该是遵循JavaBean 设计模式的POJO,其中getter/setter 封装了属性。

我绝对不会制作或称它为托管 bean。只需将其设为 a 的属性即可@ManagedBean。例如 DTO 或 JPA @Entity


支持托管 Bean:这种类型的托管 bean 参与 MVC 设计模式的“视图”关注点。backing-bean 的目的是支持 UI 逻辑,并且与 JSF 视图或 Facelet 组合中的 JSF 表单具有 1::1 的关系。尽管它通常具有带有关联 getter/setter 的 JavaBean 样式属性,但这些是 View 的属性,而不是底层应用程序数据模型的属性。JSF backing-beans 也可能有 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。


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

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


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

这对我来说真的没有意义。支持 bean 通常与单个视图相关联。这听起来太像您选择的命令组件中ActionListener使用的实现。<f:actionListener>绝对不是托管bean。

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

于 2011-08-28T20:58:47.750 回答