JSF 服务层

Posted

技术标签:

【中文标题】JSF 服务层【英文标题】:JSF Service Layer 【发布时间】:2012-10-12 06:15:07 【问题描述】:

我不确定我在 JSF 中使用 MVC 环境的方法是否是最好的方法。由于我试图充分利用 JSF,我想知道我的服务层(或模型,用 MVC 术语来说)应该如何“设计”。

我知道 View-Controller 比率应该是 1 比 1(排除了例外情况)。 现在我应该以什么方式设计我的服务层?我应该使用一项大服务(不这么认为)吗?如果不是,我应该根据什么拆分我的服务?

请注意,我的服务将从 Bean(MVC 术语中的控制器)调用,并且服务本身将在必要时使用 JPA 调用 DAO。

提前致谢

【问题讨论】:

【参考方案1】:

服务层(业务模型)应围绕主要实体(数据模型)设计。例如。 UserService 代表UserProductService 代表ProductOrderService 代表Order,等等。您绝对不应该拥有一个庞大的服务类左右。这是极其紧密的耦合。

对于服务层 API 本身,Java EE 6 提供 EJB 3.1 作为服务层 API。在黑暗的 J2EE 时代,很久以前,当 EJB 2.0 难以开发时,Spring 更多地被用作服务层 API。现在有些人仍在使用它,但由于 Java EE 6 已经整合了从 Spring 中学到的所有优秀经验,所以它变成了superfluous。请注意,EJB(和 JPA)在 Tomcat 等准系统 servlet 容器中不可用。您需要在其上安装例如 OpenEJB(或仅升级到 TomEE)。

无论选择何种服务层 API,最好的办法是通过完全在服务层中执行业务工作来保持您的 JSF 支持 bean(动作)侦听器方法尽可能流畅。请注意,服务层本身应该有任何 JSF 依赖项。因此,服务层代码中javax.faces.* 的任何(内)直接导入都表明设计不佳。您应该将特定的代码行保留在支持 bean 中(通常是根据服务调用结果添加面孔消息的代码)。通过这种方式,服务层可重用于其他前端,例如 JAX-RS 甚至普通 servlet。

您应该了解,Java EE 应用程序中服务层的主要优势是容器管理事务的可用性。对@Stateless EJB 的一个服务方法调用实际上算作单个数据库事务。因此,如果在服务方法调用调用的使用@PersistenceContext EntityManager 的任何DAO 操作之一期间发生异常,则将触发完成 回滚。这样,您最终会得到一个干净的 DB 状态而不是一个脏 DB 状态,因为例如第一个 DB 操作查询成功,但第二个没有。

另见:

Creating master-detail pages for entities, how to link them and which bean scope to choose When is it necessary or convenient to use Spring or EJB3 or all of them together? JSF Controller, Service and DAO

【讨论】:

所以.. 如果您将其与 DAO(以及为此,实体)进行比较,该服务的比率将为 1 比 1?您的其余解释是 100% 清楚的,我服务的目的已经可以(所以业务逻辑,没有 JPA 逻辑,没有 JSF 逻辑)。我将需要更多地研究正确的范围等等。再次感谢您:) 不完全是 1:1。您可以在单个服务类中注入多个 DAO。取决于实体本身是否有任何子实体。 @BalusC 将一个休眠类声明为 JSF bean 是否很常见?例如,我有一个公司视图(它具有名称、地址、联系人等属性)。我遇到了问题,因为除了所有 Company 属性之外,我还有一个 List。它给了我一个错误,因为它是一个休眠类,它试图找到一个不存在的 List 类型的列。我能够通过使其瞬态来解决问题。但这是一个好习惯吗? @Erick:查看“另请参阅”链接以获取在支持 bean 类中正确使用实体类和服务类的具体示例。 您应该明白,Java EE 应用程序中服务层的主要优势是容器管理事务的可用性。我喜欢这个【参考方案2】:

如果您的应用中的实体很少,那么服务和模型实体之间的 1:1 比例可能还不错。但如果是大应用,服务就太多了。

服务的数量取决于您正在设计的应用的用例。一旦在分析阶段确定了它们,就必须根据它们的功能将它们分成几组。每组用例都是一个服务,每个用例都是该服务中的一个方法。每个服务可以管理多个模型实体(您必须在其中注入执行其功能所需的 DAO)。通常,服务的用例管理模型类图中相互关联的模型实体。服务可能遵循“最大内聚/最小耦合”的良好做法。

DAO 与模型实体的比例为 1:1。每个 DAO 对其实体执行 CRUD 操作和查询。如果一个方法需要查询 2 个关联实体,根据业务概念放到更合适的 DAO 中。

在 JSF 表示层中,我在页面和控制器之间没有 1:1 的比例,这将是太多的控制器。我将执行每个服务的用例所需的所有页面组合到一个控制器中。因此,控制器和服务之间的比例是 1:1,将每个服务注入到其页面执行其用例的控制器中。

当然,这些是一般原则。您可能在应用程序中有一些特殊情况会破坏它们,但它们很少。

您可能不会有太多的服务和控制器,但也不会太少,因为那样它们就会有太多的逻辑和字段。你必须达成妥协。

【讨论】:

以上是关于JSF 服务层的主要内容,如果未能解决你的问题,请参考以下文章

JSF Web框架与Facelets表现层技术

JSF Web框架与Facelets表现层技术

Spring JSF 集成:如何在 JSF 托管 bean 中注入 Spring 组件/服务?

Java Server Faces:仅在业务逻辑层中进行验证

JSF 语言环境:浏览器定义的语言似乎被忽略了

JDBC持久层? [关闭]