JSF支持bean结构(最佳实践)


118

我希望在这篇文章中,我可以得到人们对于JSF页面和后备bean之间的接口的最佳实践的看法。

我永远无法解决的一件事是我的后备豆结构。此外,我从未找到关于该主题的好文章。

哪些属性属于哪个后备豆?在什么时候向给定的bean添加更多属性而不是创建一个新bean并将属性添加到给定bean?对于简单的应用程序,考虑到将一个bean注入另一个bean所涉及的复杂性,在整个页面上只有一个backing bean是否有意义?支持bean应该包含任何实际的业务逻辑,还是应该严格包含数据?

随时回答这些问题以及可能出现的任何其他问题。


至于减少JSF页和后备bean之间的耦合,我决不允许JSF页访问任何后备bean属性的属性。例如,我绝对不允许:

<h:outputText value="#{myBean.anObject.anObjectProperty}" />

我总是要求类似:

<h:outputText value="#{myBean.theObjectProperty}" />

支持bean值为:

public String getTheObjectProperty()
{
    return anObject.getAnObjectProperty();
}

例如,当我遍历一个集合时,我使用包装器类以避免钻取到数据表中的对象。

通常,这种方法对我来说感觉“正确”。它避免了视图和数据之间的任何耦合。如果我错了,请纠正我。


您能否举个例子:当我遍历一个集合时,我使用包装器类来避免向下钻入数据表中的对象。
Koray Tugay

2
欲了解更多信息,请参阅BalusC的答案在stackoverflow.com/questions/7223055/...
扎克核心提示:

Answers:


146

您可能需要检查一下:在不同类型的JSF托管bean之间进行区分

以下是Neil Griffin在上述文章中定义的各种bean类型的描述:

  • Model Managed-Bean通常为会话范围。 这种类型的托管bean参与了MVC设计模式的“模型”关注。当您看到“模型”一词时,请考虑一下数据。JSF模型bean应该是遵循JavaBean设计模式且具有getters / setter封装属性的POJO。模型bean的最常见用例是成为数据库实体,或仅表示数据库查询结果集中的一组行。
  • 支持Managed-Bean通常请求范围。这种类型的托管bean参与了MVC设计模式的“视图”关注。支持bean的目的是支持UI逻辑,并且与JSF视图或Facelet组合中的JSF表单具有1 :: 1的关系。尽管它通常具有带有关联的getter / setter的JavaBean风格的属性,但它们是View的属性,而不是基础应用程序数据模型的属性。JSF支持bean也可以具有JSF actionListener和valueChangeListener方法。
  • Controller Managed-Bean通常是请求范围。 这种类型的托管bean参与了MVC设计模式的“控制器”问题。控制器bean的目的是执行某种业务逻辑并将导航结果返回给JSF导航处理程序。JSF控制器bean通常具有JSF动作方法(而不是actionListener方法)。
  • 支持Managed-Bean通常是会话或应用程序范围。 这种类型的bean在MVC设计模式的“视图”方面“支持”一个或多个视图。典型的用例是为一个以上的JSF视图中的JSF h:selectOneMenu下拉列表提供一个ArrayList。如果下拉列表中的数据特定于用户,则Bean将保留在会话范围内。但是,如果数据适用于所有用户(例如省的下拉列表),则该bean将保留在应用程序范围内,以便可以为所有用户缓存它。
  • Utility Managed-Bean通常是应用程序范围。 这种类型的bean为一个或多个JSF视图提供了某种“实用程序”功能。一个很好的例子就是FileUpload bean,它可以在多个Web应用程序中重用。

8
这是一篇很棒的文章。我以前从未看过它,也很高兴您发布了它。投票否决的人都是疯子。它不是iceFaces特有的。
Zack Marrapese

2
与实际文章的链接似乎已消失。
Bill Rosmus

可以在此处
ChrLipp 2012年

10
不过,我无法确定这个答案目前是71个投票。不管是谁,根据那些规则实现其JSF​​应用程序的人员,无疑都必须保证JSF是一个非常不透明的框架,而他们的JSF应用程序却是一个大代码烂摊子,他们都将责任归咎于JSF本身,而不是基于错误的教训(所谓的“错误的方法”)。学习了“最佳实践”。
BalusC

这些bean的逻辑是在浏览器而不是服务器中执行的吗?
eskalera 2014年

14

好问题。迁移到JSF时,我遇到了同样的困境。这实际上取决于您的应用程序。我来自Java EE领域,因此建议您在后备bean中尽可能少使用业务逻辑。如果逻辑与页面的显示纯粹相关,那么可以将其放在辅助bean中就可以了。

我相信JSF的(许多)优势之一实际上是您可以直接在托管bean上公开域对象。因此,我强烈建议<:outputText value="#{myBean.anObject.anObjectProperty}" />您使用该方法,否则您最终会在手动公开每个属性时为自己做过多的工作。此外,如果封装了所有属性,则在插入或更新数据时会有些混乱。在某些情况下,单个域对象可能不足。在那种情况下,我准备一个ValueObject,然后再将其暴露在bean上。

编辑:实际上,如果您要封装要公开的每个对象属性,我建议您改为将UI组件绑定到支持bean,然后将内容直接注入到组件的值中。

就bean结构而言,对我而言,转折点是我无视所有有关构建Web应用程序的知识,而开始将其视为GUI应用程序。JSF非常模仿Swing,因此开发Swing应用程序的最佳实践通常也适用于构建JSF应用程序。


感谢您的见解。我从来没有在摆动应用程序方面做过什么(除了很久以前的学术项目以外)。摇摆应用程序的一些良好原理是什么?另外,为什么在插入和更新值时一团糟?对我来说一样吗?
Zack Marrapese

5

我认为与支持bean最为重要的是分离其逻辑。如果您有CMS系统的首页,那么将每段代码放入一个bean中将是一种不好的做法,因为:

  1. 豆最终会变得很大
  2. 如果其他人正在对登录页面进行故障排除,那么其他人更容易找到所需的内容,如果他们可以轻松地仅查找loginBean.java文件。
  3. 有时候,您有一些与其他代码明显不同的小功能,将它们分开,我想如果您已经有了一个不错的bean,那么您可以更轻松地将代码重新开发/扩展为更大的代码结构体。
  4. 如果有/需要做一个这样的声明,那么拥有1个大bean可以使它更多地依赖于内存,而不是通过执行LoginBean loginBean = new LoginBean();使用实际需要的功能。(如果我在这里错了,请纠正我??)
  5. 我认为,分离bean就像分离方法。您不希望有一种运行超过100行的大型方法,而是将其与处理特定任务的新方法分开。
  6. 请记住,您之外的其他人很可能也必须从事您的JSF项目。


至于耦合,我认为允许您的JSF页面也访问backingbean对象中的属性并不是一个麻烦的问题。这是JSF内置的支持,实际上只是使阅读和构建imo更容易。您已经准备好严格分离MVC逻辑。通过这样做,您可以节省与backingbean中的getter和setter相关的大量操作。例如,Web服务给了我一个非常大的对象,我需要在演示文稿中使用一些属性。如果我要为每个属性设置一个getter / setter方法,那么我的bean将至少增加100行变量和获取属性的方法。通过使用内置的JSF功能,可以节省时间和宝贵的代码行。

即使问题已经标记为“已回答”,我也只有2美分。


1
但是,如果您的bean中有一个巨大的对象,并且您从JSF页面中有15个EL函数(例如)深入到该对象中,那么您不仅会与bean绑定在一起,而且会与该对象绑定在一起。因此,在不破坏UI的情况下很难删除该对象。
Zack Marrapese

1
但是,您的支持bean也不会与该对象绑定吗?和您的用户界面绑定到支持bean?然后,当您必须对其进行修改时,必须在UI和Bean中都更改所有的getter / setter方法。
克里斯·戴尔2009年

4

我可能不会回答您的每一个问题,因为似乎很少有个案视情况而定。

  • 在您的后备bean中具有业务逻辑很好。这取决于你来自哪里。如果您正在练习域驱动的设计,那么您将很容易将业务逻辑包含在支持bean中,或者也可能是持久性逻辑。他们争辩说为什么这么愚蠢的反对。对象不仅应承载状态,而且还应承载行为。另一方面,如果您考虑使用传统的Java EE做事方式,您可能会觉得自己的后台bean中有数据,后者也可以是您的实体bean,以及某些会话bean之类的其他业务和持久性逻辑。也可以。

  • 在整个页面上只有一个后备bean是非常好的。仅此一点我就看不到任何问题。这可能看起来不正确,但这取决于情况。

  • 您的其他问题更多地取决于您手头的情况。我希望在这里进行域驱动,将属性添加到现有属性或为此创建一个新bean可能是合适的。哪个更适合。我认为没有任何灵丹妙药。

  • 哪些属性属于哪个后备bean。好吧,这不取决于域对象吗?或者可能是问题还不清楚。

而且,在给定的代码示例中,我看不到任何巨大的好处。


例如,如果我们要从使用通过JDBC查询创建的自制POJO更改为字段名称稍有不同的Hibernate实体,我们不仅必须更改后备bean。我们还必须更改JSF页面。我的代码示例并非如此。只是换豆子。
Zack Marrapese

在这种情况下,您可以使您的后备豆成为实体。那么您只需要更改JSF页面。还是取决于您为什么仍要更改属性名称?仅当您重命名字段以匹配数据库列名时才有意义。但这是另一种情况。
Adeel Ansari 2009年

4

我不必每页只保留一个备用bean。这取决于功能,但是大多数时候我每页只有一个bean,因为大多数页面只能处理一种功能。例如,在页面上,我有一个注册链接(我将与RegisterBean链接)和一个购物篮链接(ShoopingBasketBean)。

我确实使用此<:outputText value =“#{myBean.anObject.anObjectProperty}” />,因为我通常将支持bean作为保存数据对象的动作bean。我不想在备用bean中编写包装程序来访问数据对象的属性。


0

我喜欢在没有View的情况下测试业务代码,因此我将BackingBeans视为从View到Model代码的接口。我从来没有在BackingBean中放置任何规则或过程。该代码进入服务或助手,允许重用。

如果使用验证器,请将其从BackingBean中取出,并从验证方法中引用它们。

如果您访问DAO来填充“选择”,“单选”,“复选框”,请始终在BackingBean中执行此操作。

相信我!。您可以将JavaBean注入BackingBean,但尝试将BackingBean注入另一个。您将很快了解维护和理解代码。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.