JSF 中的最佳实践:模型、动作、getter、导航、阶段监听器

Posted

技术标签:

【中文标题】JSF 中的最佳实践:模型、动作、getter、导航、阶段监听器【英文标题】:Best practices in JSF: model, actions, getters, navigation, phaselisteners 【发布时间】:2011-06-12 22:07:38 【问题描述】:

我参与了一个重构 JSF 实现的项目。现有代码没有遵循正确的 JSF 标准。为了实现这一点,我正在学习 JSF 中的所有概念(我已经亲身体验过 JSF)。具体来说,我想问一下我的想法。

在MVC模式中,JSF中的模型组件是什么?是托管 Bean 吗? 在操作方法中编写业务逻辑是个好主意吗?我已经看过数百行用动作方法编写的。 您认为我们可以在 getter 方法中编写任何逻辑吗?在 JSF 生命周期中调用了多少次 getter 或 setter。 编写 faces-config.xml 的常规方法是什么。我在一个文档中读到,它说一起为该 bean 编写托管 bean 声明和导航案例是一种很好的做法。它将更具可读性。 编写阶段监听器会影响响应时间。例如,我正在编写一个逻辑来解析 PhaseListener 中的请求参数并做一些逻辑。对此有什么建议吗?

请回答以上问题。如果我对答案很清楚,那么我会提出更多问题。

【问题讨论】:

【参考方案1】:

请注意,即使您标记了 [icefaces],此答案通常也适用于 JSF,而不适用于 IceFaces。

在 MVC 模式中,JSF 中的模型组件是什么?是托管 Bean 吗?

没错。视图是 JSP/Facelets 页面。控制器是FacesServlet。有关它如何“在幕后”工作的更多详细信息,另请参阅 this answer。

在操作方法中编写业务逻辑是个好主意吗?我看过数百行写在 action 方法中的代码。

您还可以将调用委托给 EJB 等业务服务。通过这种方式,您可以抽象出业务细节。在“简单”的应用程序中,将那部分放在一边并在托管 bean 中做所有事情通常不会有什么害处。但是,一旦您想更改业务逻辑(例如,针对不同的客户或出于演示目的等),那么拥有服务会更方便,因此您无需更改托管bean,但你只需要编写另一个业务接口的实现类。

你认为我们可以在 getter 方法中编写任何逻辑吗?在 JSF 生命周期中调用了多少次 getter 或 setter。

如果业务逻辑需要在每个 getter 调用上执行,那么就这样做(然而这在现实世界中不太可能发生,预计会出现疯狂的日志记录或特殊的延迟(重新)加载情况)。但是,如果业务逻辑只需要在每个操作、事件、请求、会话或应用程序范围内执行一次,那么它肯定必须在其他地方执行。另见this answer。

getter 被调用多少次应该是您最不关心的问题。 getter 除了返回有问题的属性之外什么都不做。在输出值中调用时,每个请求可以调用一次。在输入值中调用时,每个请求可以调用两次。在数据表/重复组件内时,将调用乘以行数。在渲染属性内,将调用乘以 6~8 倍。

编写 faces-config.xml 的常规方式是什么。我在一个文档中读到,它说一起为该 bean 编写托管 bean 声明和导航案例是一种很好的做法。它将更具可读性。

我自己很少使用导航箱,我的faces-config.xml 中通常没有。我总是发回相同的视图(返回nullvoid,然后有条件地渲染/包含结果。对于页面到页面导航,我不使用 POST 请求(对于导航案例是强制性的),只是因为这对 UX(用户体验;浏览器后退按钮的行为不正常,浏览器地址栏中的 URL 总是落后一步,因为默认情况下是转发,而不是重定向)和 SEO(搜索引擎优化;搜索机器人没有) t 索引 POST 请求)。我只使用 outputlinks 甚至纯 html <a> 元素进行页面到页面导航。

此外,在 JSF 2.0 中,faces-config.xml 中的托管 bean 定义和导航案例在技术上是不需要的。另见this answer。

编写阶段监听器会影响响应时间。例如,我正在编写一个逻辑来解析 PhaseListener 中的请求参数并做一些逻辑。对此有什么建议吗?

这与过早优化类别中的 servlet 过滤器类似。担心他们的表现通常是没有意义的。这是每个 Saldo 通常只额外增加一两行代码。真的没什么好担心的。当您将那段代码复制粘贴到所有类时,您会遇到更大的问题。如果您真的认为它会影响性能,请先对其进行分析,然后我们可以讨论它。

【讨论】:

【参考方案2】:

在 MVC 模式中,JSF 中的模型组件是什么?是托管 Bean 吗?

我建议这样做:

视图层(由一个迷你 MVC 组成):

userForm.xhtml

用户控制器

UserController.get/setUser

控制器层:

用户服务

UserDAO

用户

模型层:

数据库

在操作方法中编写业务逻辑是个好主意吗?我看过数百行写在 action 方法中的代码。

在我的示例中,将业务逻辑放在 UserService 的方法中。 UserController 的 action 方法除了调用 UserService 中的方法,捕获任何异常并格式化显示的下一个网页的响应外,并没有做更多的事情。

你认为我们可以在 getter 方法中编写任何逻辑吗?在 JSF 生命周期中调用了多少次 getter 或 setter。

最好让 getter/setter 只做获取/设置。没有逻辑。

编写 faces-config.xml 的常规方式是什么。我在一个文档中读到,它说一起为该 bean 编写托管 bean 声明和导航案例是一种很好的做法。它将更具可读性。

我将我所有的托管 bean 一起声明。并一起声明我所有的导航规则。

编写阶段监听器会影响响应时间。例如,我正在编写一个逻辑来解析 PhaseListener 中的请求参数并做一些逻辑。对此有什么建议吗?

不确定您到底在做什么,但您不必手动解析请求参数。 JSF 应该为您将表单的值直接注入到视图模型中。也许我需要更多关于你想要做什么的信息。

希望这会有所帮助。

【讨论】:

有人能推荐一个使用这种方法的示例/教程吗?

以上是关于JSF 中的最佳实践:模型、动作、getter、导航、阶段监听器的主要内容,如果未能解决你的问题,请参考以下文章

JSF 中“返回”导航链接的最佳实践

中止操作方法的最佳实践

JSF:AJAX 测试最佳实践

JSF/Facelets/JSTL 条件显示最佳实践

JSF 最佳实践:自定义组件和 JavaScript

JSF 2.0 上用户身份验证的最佳实践?