SpringBoot中能在控制器中映射dto吗?


我的经理告诉我,最佳实践是:将从服务层返回的 dto 映射到控制器。
我的想法是:控制器只有一行,只需将逻辑委托给服务层并返回响应实体,因此在能在控制器中映射一个dto。

网友建议:
1、因为你可能需要在一个服务中使用另一个服务。然后你正在混合领域对象和DTO:DTO 是外部合约,所以在我的工作中,控制器只是负责与实体对象之间的转换。

2、如果您想对服务层做到真正严格和干净,您的内部服务不应使用通过 API 公开的相同 DTO,这为您提供了最大程度的解耦。

因此,您的服务应该返回一个内部对象或记录,并且您应该有另一个服务从该对象转换为 API DTO,这样您的控制器就会有一个流程,例如将请求 DTO 转换为内部服务对象、调用内部服务、调用服务来转换内部服务结果响应 DTO。

这样,领域部分只理解领域对象。控制器应该使用适配器 服务,这个服务至少可以在 API 对象与域对象之间进行转换或映射

3、控制器不应执行任何业务逻辑。它还有其他责任。验证只是这些职责之一。

一般来说,控制器(例如 API 或表示层)负责将从业务层获取的信息转换为客户端可以理解的表示形式。这不可能总是在一行中完成。

  • 控制器可能需要为其客户端设置 cookie。控制器可能需要将其获取的数据转换为符合 hatoas 的(例如 Hal 风格)形式。
  • 控制器可能不是服务 api,它也可能是 html api,需要执行更多操作,而不仅仅是从业务层返回数据。
  • 控制器甚至可能根本不是控制器,它可能是一个为事件队列转换来自业务层的数据的组件。

我们将这些问题分开的原因是,您不希望这些责任中的任何一个泄漏到您的业务逻辑中。

鉴于此,您不应该将自己简化为“我的控制器只允许包含一行代码”之类的简单规则,因为这会导致您将技术代码从控制器泄漏到业务层。

4、你的问题没有简单的对错之分,因为答案取决于问题:你想封装什么?

  • 如果您在控制器中映射 dto,则 dto 将成为表示或 api 逻辑的一部分,从而主要将服务的客户端封装在服务内部的更改中。
  • 如果您在服务中映射 dto,则 dto 将成为服务业务层的一部分,从而主要封装服务的表示/api 层,使其免受业务层中的更改的影响。

因此,问题就变成了:您期望每个层多久更改一次?
  • 如果您预计业务逻辑会频繁更改,那么在那里引入 dto 层可能是明智的选择,这样业务逻辑的客户端(控制器)就不必随着业务层的每次更改而更改。
  • 如果您希望 api 经常更改或者希望封装服务的内部,那么在那里引入 dto 层可能是明智的选择。

您甚至可能对这两个问题的回答都是“是”,因此在 api/表示层以及业务层中引入 dto 层可能是明智的。

5、我们曾经将 DTO 映射到控制器中,但一旦映射中发生了业务逻辑,我就把它移到服务层。