21

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

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

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

提前致谢

4

2 回答 2

41

服务层(业务模型)应该围绕主要实体(数据模型)设计。例如UserServicefor User, ProductServicefor Product, OrderServiceforOrder等。你绝对不应该有一个庞大的服务类左右。那是极端紧密的耦合。

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

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

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

也可以看看:

于 2012-10-22T13:55:15.560 回答
3

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

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

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

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

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

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

于 2014-10-29T17:51:43.390 回答