我真的需要服务层吗?

30

我的Web应用程序使用Spring MVC + Hibernate编写。

  • 我的模型是“Customer”实体POJO。
  • 我有一个名为“CustomerDAO”的DAO对象,“saveCustomer(c)”方法包含与Hibernate交互的代码;
  • 然后我创建了一个“CustomerService”,其中包含一个“saveCustomer(c)”方法,该方法仅将客户对象传递给DAO进行保存;
  • 最后有“CustomerController”和customer.jsp,它们负责视图层,jsp的表单字段在控制器端绑定到Customer对象。控制器调用服务。

我看到很多应用程序都遵循这个(最佳)实践,但我想知道为什么需要服务层。

也许出于解耦的目的很有用:我可以向控制器展示通用的门面,并注入HibernateDAO、GaeDAO、MyDAO等到服务中....但我也可以不使用服务,而是使用接口来实现。

我还想到:验证。我将在服务中进行我的客户验证,但是......在Spring控制器中进行验证更加方便。

请帮助我理解这个概念 :)

5个回答

26

你并不一定需要使用服务层,不过这有助于:

  • 解耦你的组件
  • 在服务层中强制执行特定的业务规则,这应该与你的存储库无关
  • 让一个服务门面管理一个或多个存储库。考虑以下示例
class Service {
  private DatabaseBarRepo barRepo;
  private DatabaseFooRepo fooRepo;

  @Transactional
  public void serviceRoutine() {
     barRepo.doStuff();
     fooRepo.doStuff();
  }
}

在这里,我们让两个独立的存储库参与同一个事务。尽管原则对于其他系统也是有效的,但这是特定于数据库的。


1
该服务还可以为一个或多个控制器(例如Web控制器和JSON/WS API)提供共享逻辑。 - seanhodges
4
通过这种方式,你也可以轻松将服务(服务方法)暴露为Web服务... - Matjaz Muhic
非 UI 客户端可以直接与您的服务层交互,该层可以验证请求。 - Blue Sky

22

关键在于事务行为。如果没有服务层,你在哪里划分事务?

  • 在表示层:那不是事务划分的所在,而且你无法使用声明式事务划分
  • 在 DAO 层:因为它将使用两个不同的 DAOs,所以您将无法在单个事务中创建客户及其联系人(例如)。

此外,您希望 UI 层尽可能简单,并将业务代码(有时比简单调用 DAO 方法复杂得多)隔离在特定组件中。这使得

  • 通过模拟服务层来对 UI 层进行单元测试
  • 通过模拟 DAO 层来对服务层(业务代码)进行单元测试

2
在“领域门面”样式中的服务层是领域模型的轻量级门面,本身不实现任何业务逻辑,但指示事务。如果使用EJB(而不是Spring),则更加明显,其中无状态会话bean具有容器管理的事务。 - Raedwald

7

目前,您的服务层非常简单,因为您的服务只是对数据库访问进行了简单的封装。这就是应用程序的全部吗?如果不是,当您开始构建非平凡部分时,您的服务层将会扩展。


6
你可以通过创建一个BaseService,将所有的CRUD操作委托给注入其中的BaseDAO,从而节省冗余代码。
除了CRUD操作外,几乎所有其他操作都有单独的业务逻辑和数据库特定操作的逻辑。另外,你可以通过在服务层方法上注解@Transactional来跨越多个数据库操作进行事务处理。

2

在服务层中,还有其他需要处理的事情。有时候需要在将任何操作传递给DAO之前应用业务规则。有时候一个服务需要与其他服务、DAO进行交互以满足业务规则的需求。

请告诉我们如何在没有服务器层和接口的情况下完成这些工作,您的高级想法将帮助我更好地向您解释。


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