【问题标题】:Using Services and DAOs in spring mvc controller在 spring mvc 控制器中使用服务和 DAO
【发布时间】:2013-04-20 11:07:28
【问题描述】:

我正在构建一个 Web 应用程序,该应用程序主要由来自后端/数据库的数据的 CRUD 操作构成。在某些情况下,我必须编写业务逻辑(我相信随着我们深入开发,我们将构建更多的业务逻辑)。目前,对于我正在创建的每个 UI 屏幕,我创建了一个模型类、服务类、DAO 类、一个控制器(本质上是 servlet)和一堆 jsp 页面。在大多数情况下,服务类只是调用 DAO 中的方法来传入模型对象。本质上,我们使用模型类来映射来自 UI 屏幕的数据。因此,控制器将在提交表单时填充模型对象。我已经开始使用服务类来保持从 web 层到 DAO 层的分离层。但有时我觉得服务类只是添加了不必要的 API 调用级别,我认为我可以将 DAO 注入 Controller 并更快地完成任务。我只想在需要执行其他业务逻辑时才使用服务类。如果你必须设计一个应用程序,你会考虑哪些因素使用控制器->DAO 与控制器->服务->DAO 控制流?

【问题讨论】:

  • 当我开始我现在的工作时,我进入了一个已经存在的项目。我已经在这里待了一年多一点。老实说,我刚刚意识到应该有一个单独的层来注入 DAO。工作中的项目只是将它们注入到控制器中。既然我知道了这一点,并且已经为原子性的好处做好了准备,我认为拥有一个服务层会很好,因为我们在整个应用程序中确实有多个交互实体。

标签: java spring design-patterns spring-mvc


【解决方案1】:

DAO 更加细化并处理一个特定的实体。服务提供宏观层面的功能,最终可能会使用多个 DAO。通常,服务用于定义事务边界以获得原子性。换句话说,如果您最终使用多个 DAO 更新多个表,则在服务中定义事务边界将有助于提交或回滚对 DB 所做的所有更改。

在您的设计中,由于您主要为各种实体执行 CRUD,因此服务似乎没有增加太多价值。但是,将基于 Web 的前端视为更新数据的一种方式。服务的使用将允许您稍后将与 Web 服务相同的功能公开给其他形式的客户端,例如第三方集成商等。

因此,总而言之,您的设计似乎符合传统做法。如果你觉得你可以基于一些共同的主题将多个服务组合成一个,这样可以减少代码的开销,那么你应该去做。归根结底,最终目标是创建可维护的代码,没有人害怕在需要时更改。

【讨论】:

  • “服务的使用”你不需要一个服务类来返回一个简单的列表/执行 crud 或作为一个 restful-api 公开。操作多个交互实体时,您需要一个单独的服务类。
  • 在提供外部应用程序时,您也需要服务。想象一下,您有一个为 Android 应用程序提供数据的 Web 服务。您可以创建一个服务层,它将获取数据并为适配器层返回 DTO(数据传输对象),该适配器层处理 REST 请求并将这些 DTO 转换为 JSON 或 XML 以发送到 Android 应用程序。
【解决方案2】:

我会参考我的答案here

总而言之,使用 Service 层的优势在于,如果您想使用 Spring Security 和角色等做任何事情,它为您提供了未来移动的空间。它允许您更原子地处理事务和 Spring它本身对此有很好的注释。

【讨论】:

  • 那么你必须经历从你的控制器中解开你的 DAO 问题的痛苦。如果您的控制器与您的 DAO 密切相关,如果您还没有构建服务层,那么这将在未来做更多的工作。
  • 因为服务应该提供关注点分离en.wikipedia.org/wiki/Separation_of_concerns。如果您引入了服务层,那么忽略该服务外观并从控制器直接访问 DAO 将是一种不好的做法。虽然最初您会通过最初不需要服务层来打破 DRY 规则,但事实上它是 SoC 对任何重构来说在未来都会更加痛苦。
  • 我将把它留在这里stackoverflow.com/questions/3688664/…,因为它基本上总结了我的理由,即为什么为可能会变得复杂的应用程序提供服务层是一个好主意。
【解决方案3】:

在处理多个aggregate root 时使用服务类。

将存储库(也称为返回集合的 dao)或 dao 直接注入控制器,无需额外的层/类来执行基本获取。

仅在必要时使用服务类,否则您的代码量是所需的两倍。

您可以使存储库通用,并使用@Transactional(propagation = Propagation.REQUIRED) 进行注释,这会强制事务存在,但如果已经存在则不会创建新的。因此,如果您稍后在一个服务类方法中使用多个存储库,您将只有一个事务。

【讨论】:

    【解决方案4】:

    在 Pro-Spring-3 的书中,他们提到了下面一行,用于带有 JPA2 的控制器

    Once the EntityManagerFactory had been properly configured, injecting it into your service layer
    classes is very simple.
    

    他们使用与服务和存储库相同的类,如下所示:

    package com.apress.prospring3.ch10.service.jpa;
    // Import statements omitted
    @Service("jpaContactService")
    @Repository
    @Transactional
    public class ContactServiceImpl implements ContactService {
    private Log log = LogFactory.getLog(ContactServiceImpl.class);
    @PersistenceContext
    private EntityManager em;
    // Other code omitted
    }
    

    但如果您要使用 spring-data CRUDRepository 或 JPARepository,那么您的 DAO 将是接口,您必须创建服务层来处理您的代码

    【讨论】:

      猜你喜欢
      • 2021-03-19
      • 1970-01-01
      • 2014-10-16
      • 2013-07-18
      • 2018-01-31
      相关资源
      最近更新 更多