【问题标题】:Whats the best practice of using Controller,Service and Repository annotations?使用 Controller、Service 和 Repository 注释的最佳实践是什么?
【发布时间】:2015-09-23 05:39:47
【问题描述】:

我对在 Spring-MVC 中使用 @Controller@Service@Repository 感到很困惑。

我有几个问题,希望能得到解答。

  • 我知道控制器用于接收来自视图的请求并向视图发出请求以向用户显示结果。我的问题是,我可以在带有控制器注释的类中进行多大程度的处理?我应该在服务注释类中进行所有处理并保持控制器仅用于接收请求和返回响应吗?我想知道最佳做法是什么?

    假设我需要调用服务注释类的不同方法来处理结果,我应该从控制器全部调用它们还是将它们传递给服务注释类? (这只是一个例子)

  • 如果我不想处理结果而只想向数据库发送请求并接收结果,我还需要在控制器和存储库之间有一个服务注释类吗?

    假设我收到一个产品 ID,并想检索并显示产品的详细信息。(这只是一个示例)

【问题讨论】:

  • 现在你可能没有任何业务逻辑可以放入服务层,但你永远不知道未来会发生什么。所以最好通过服务类委派您的呼叫。
  • @NamanGala 谢谢第一个要点怎么样?
  • 我建议将您的业务逻辑保留在服务层中,并且只查看控制器中的特定代码。对于您的示例,这取决于要求,如果它具有完整的功能,那么我会将其保留在服务层中,如果它只是从存储库中收集一些数据,那么我将仅从控制器进行不同的服务方法调用。

标签: java spring spring-mvc


【解决方案1】:

我认为这几乎不是任何“最佳方法”,而是适合您需要的方法。这是我在过去的项目中使用的方法,它基于领域驱动设计。

  1. 表示层:控制器(@Controller)

    仅负责呈现业务功能(在应用服务层中提供)。因此,主要是委托给 App Service,进行数据按摩和与演示相关的逻辑。

  2. 应用服务层:应用服务(@Service)

    从高层次上讲,它代表了业务用例。因此,在方法上设置了事务边界(因为每个方法都是一个用例,因此是一个工作单元)。由于我反对使用贫血模型,真正的业务逻辑应该在领域模型层。该层主要利用领域层来组成一个有意义的用例。主要是数据转换(取决于您的设计)和领域层工件的委托。

  3. 域层:模型、域服务(@Service)、存储库(@Repository)等

    业务逻辑位于域模型或域服务中。存储库是检索域模型的工件。

  4. 基础设施层

    一些域工件的依赖于基础架构的实现。

回到你的问题:

  • 没有对错之分。如果您正在制作一个完全独立的简单应用程序,那么拆分控制器和应用程序服务层的角色可能没有任何好处。此外,对于那些习惯于贫乏模型开发的人来说,您可能需要一个服务来将您的业务逻辑放入其中。所以,您需要问自己,在您的设计中设置特定层的目的是什么?对你来说真正有意义的东西。对于我的方法,我认为对于哪一层该做什么已经很清楚了。如果你愿意,可以作为参考。

  • 类似的回答:如果你是在你的Controller中做Presentation + Application Service的角色,没有特殊的理由去组成另一个Service。但是如果你想维护一个表现中立的应用服务层,那么你应该通过你的应用服务提供那些“CRUD”操作。

【讨论】:

  • 谢谢,你说的中立是什么意思?我收到产品 ID 并使用它来显示所选产品的详细信息。
  • 我的意思实际上是表示层技术中立。现在我们可能会选择使用 Spring MVC,但稍后我们可能会使用其他东西,如 CXF 或您的自定义协议。通过抽象出表示层并将应用服务保留为普通的 pojo,您可以轻松地替换表示层或通过其他渠道重用相同的用例。同样,它可能不适用于您,这在很大程度上取决于您的设计决定。
【解决方案2】:

这取决于要求,我认为您最好保持控制器清洁,它们用于演示,因此您应该只保留与演示层相关的任何内容,但是,如果您需要将输入传递给服务类并从那里调用其他服务方法,我想说不要在服务类中创建新方法,只需直接调用服务方法即可。

假设这些方法在服务类中,我认为将输入发送到服务类并在其中包含以下代码是没有意义的。我建议将此代码保留在控制器中并调用以下方法:

if(input is valid){
      result1 = serviceClass.dothisstuff(input);
      result2 = serviceClass.thenthisstuff(result1);
}else{
      result1 = serviceClass.dothosestuff(input);
      result2 = serviceClass.thenthosestuff(result1);
}

为了将来的需求,我会说始终使用所有三层。

【讨论】:

    【解决方案3】:

    将 cmets 转换为答案。

    • 我建议将您的业务逻辑保留在服务层中,并且只查看控制器中的特定代码。对于您的示例,它主要是意见基础,并且取决于要求,如果它具有完整的功能,那么我会将其保留在服务层中,如果它只是从存储库中收集一些数据,那么我将仅从控制器进行不同的服务方法调用.
    • 现在您可能没有任何业务逻辑可放入服务层,但您永远不知道将来会发生什么。所以最好通过服务类委派您的呼叫。

    【讨论】:

      猜你喜欢
      • 2011-03-09
      • 1970-01-01
      • 2015-03-18
      • 1970-01-01
      • 2011-03-30
      • 2017-11-17
      • 2014-07-05
      • 2018-03-13
      • 1970-01-01
      相关资源
      最近更新 更多