JSF最佳实践:表单、数据表等方面

4

我应该在JSF中的每个表单、数据表等都拥有一个bean吗?

例如,我有一个用于注册的表单,它只有两个字段和一个按钮,分别是:昵称、密码、提交

提交此表单应该去RegistrationFormBean还是UserBean或UserServiceBean中的某个地方?

什么是最佳实践?

谢谢。


有点相关:https://dev59.com/r2w05IYBdhLWcg3weBru - Luiggi Mendoza
你想使用JSF实现登录功能并在整个应用程序运行期间处理身份验证吗? - erencan
4个回答

4
为确定是否应该为页面中的某个组件(例如表单、数据表)创建一个独立的@ManagedBean,我认为您应该考虑设计的模块化程度。
第一个问题是:您自己应该问的问题是:该组件是否会在许多页面上重复使用?例如,在诸如ChangePasswordDeleteAccount等敏感页面上,通常您将要求用户输入当前密码以验证其身份,然后才执行任何逻辑。在这种情况下,您绝对应该有一个验证密码组件的专用bean,以便您可以一遍又一遍地重复使用该组件,而不必每次重新编写验证功能。
其次,我通常使用@ManagedBean作为保存所有相关函数的位置,这些函数工作朝着同一个目标。这些函数的分组可能相当主观。例如,我可以有一个名为CreateProduct.xhtml的页面,其中包含一个名为CreateProductBean的bean,该bean具有用于创建产品的所有函数。在这种情况下,就像1 bean per view一样。另一种方法是拥有一个名为ProductManager的bean,该bean具有与Product对象相关的所有功能(即创建、读取、更新、删除)。在这种情况下,就像1 bean for many views一样(例如,CreateProduct.xhtmlRemoveProduct.xhtml)。为了方便未来的维护和工作分割,我通常使用1 bean per view。第二种方法1 bean for many views在某些情况下也很好,但我突然还想不出一个例子: P...当我有一个好的例子时,我会更新我的答案;)。
第三,我更喜欢遵循三层MVC模型,并将后端逻辑与前端分离。例如,要在数据库中保留新帐户,我将注入一个@EJB@WebServiceRef以请求后端系统执行必要的逻辑。这绝对是以后更容易维护的:)。
因此,使用您的RegisterAccount示例,我将拥有:
- 一个名为UserExistenceValidator的bean,用于检查数据库中是否存在nickname。在注册过程中,如果用户选择已经被占用的nickname,我可以抛出错误。我还可以使用此bean检查用户是否存在于AddFriend.xhtml页面中。 - 另一个名为RegistirationFormBean的bean,用于捕获用户的输入并与后端交互以保存新帐户。

CreateProductBean和ProductManager bean都是requestscoped吗? - Koray Tugay
@KorayTugay:@Scope 是另一回事:P... CreateProductBean 应该明确为 @RequestScoped。然而,对于 ProductManager,你可能需要一个名为 List<Product> 的属性来帮助显示产品进行更新、删除等操作。在这些情况下,我大多数时候使用 @ViewScoped - Mr.J4mes
所有这些都在我在OP的问题中发布的相关链接中有解释。BalusC甚至解释了不同种类的托管bean及其各自的范围... - Luiggi Mendoza
1
@LuiggiMendoza:抱歉,我没看出BalusC的解释与我的回答有任何关系 :)。即使BalusC的回答在某种程度上与原帖问题相关,我的回答更加切合我个人认为在决定应用程序设计时重要的方面。 - Mr.J4mes

2
这实际上是一个非常有趣的话题,可以激发任何JSF爱好者的思考。因此,我无法抵制并希望进行详细解释。
其中一个非常有趣和重要的JSF发明原因是将客户端事件与服务器端应用程序代码进行连接,就像任何Swing应用程序一样,并且无需显式处理请求和响应对象。就像任何Swing应用程序一样,我们现在可以简单地将任何客户端事件(例如按钮单击)与一些服务器端代码绑定以处理该事件,而不必担心编写Web应用程序的事实和复杂性。
因此,在设计使用JSF的任何Web应用程序时,设计师可以像设计事件驱动的Swing应用程序一样专注于用户体验。因此,您可以设计视图页面并确定执行任务和在视图之间导航的事件。最后,您编写一些服务器端代码来执行这些事件中的任务,以完成所需的工作。这些服务器端代码驻留在托管bean中。
如果根据责任类型进行分类,则有几种类型的托管bean:
- 模型托管Bean - 后备托管Bean - 控制器托管Bean - 支持托管Bean - 实用程序托管Bean
您将在此文章中找到每种类型的详细信息。
您的问题是如何分配Controller Managed-Bean的责任。在分配这种责任时,需要考虑几个问题:
- 要执行的任务的复杂性。 - 可重用性。 - 责任模块化(要执行的工作类型)。 - 业务角度的模块化。 - 解耦责任等。
您可以设计系统,使用单个controller处理简单model的所有视图的CURD操作。但是,如果您需要在单个create操作中处理多个复杂事务,则将操作分离为多个controllers将是更好的设计。尽管您的注册过程非常简单,但应使用单独的controller来处理该任务。因为将任何不足够简单和相关的任务放入相同的托管bean中,这将不是一个好主意。我认为,这样就回答了您的问题!

0
在类似的情况下,我总是有一个 UserManagedBean 来处理与用户相关的操作,例如登录、注册、更改密码等等...
为了处理这些操作,我在 UserManagedBean 中放置了一个类型为 User(或其他类名)的属性,该属性对应于与用户相关的持久化数据(通常在 DB 表 user 中)。
在您的情况下,nicknamepasswordUser 类的属性。至于 submit,它将调用 UserManagedBean 中的方法来验证用户:

<h:inputText value="#{userManagedBean.user.nickname}"/>
<h:inputSecret value="#{userManagedBean.user.password}"/>
<h:commandButton value="Login" action="#{userManagedBean.loginUser}"/>

当然,loginUser方法将调用服务层的调用,该调用将调用DAO层来检查凭据是否与DB(或其他存储)匹配。
如果登录成功,则我们托管bean中的用户属性(应为会话范围)将使用从DB返回的对象进行初始化。

你是否也有类似的代码,如:如果UserManagedBean中的用户不为空,则表示该用户已登录? - Koray Tugay
你的意思是直接重定向吗?如果是,那么你应该使用一个过滤器,在其中可以实现“记住我”功能和当用户已经登录时的重定向。 - Laabidi Raissi

0

你应该为 UI 提交和数据库持久化分别创建一个数据传输对象 Bean 和一个领域 Bean。 使用控制器类,处理你的 UI JSF 提交数据并创建一个干净的领域 Bean,并使用它进行持久化。

最佳实践应该尽可能地解耦进程/实体。 此外,你的 DTO Bean 可能具有比你的领域 Bean 更多的附属数据,这些数据可能需要用于多种目的。


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