繁体   English   中英

如何在 Controller、服务和存储库模式中使用 DTO

[英]How to use DTOs in the Controller, Service and Repository pattern

我正在关注 Controller,服务和存储库模式,我只是想知道 DTO 是从哪里来的。

controller 是否应该只接收 DTO? 我的理解是你不想让外界知道底层域model?

从域 model 到 DTO 的转换应该发生在 controller 还是服务层?

在今天使用 Spring MVC 和交互式 UI 进行编程时,web 应用程序实际上有 4 层:

  • UI 层(Web 浏览器、JavaScript)

  • MVC Controller,即用@Controller注解的Spring组件

  • 服务层,即用@Service注解的Spring组件

  • 数据访问层,即用@Repository注解的@Repository组件

每次这些层与底层交互时,它们都需要发送/接收数据,通常是 POJO,以在层之间传输数据。 这些 POJO 是 DTO,也就是数据传输对象。

层与层之间只能使用 DTO,它们不一定相同,例如服务层可能会对从数据访问层接收到的 DTO 应用业务逻辑,因此服务层 API 的 DTO 与数据访问层 API 不同。 同样,Controller 可能会重新排列数据以准备呈现(分组、摘要等),因此发送到 web 浏览器的数据与从服务层接收的数据不同。

With full abstraction, the Data Access Layer's API should not reflect the technology of the Data Access, ie whether it is using JDBC, JPA, NoSQL, a web service, or some other means of storing/retrieving the data. 这意味着实体类不应出现在数据访问层之外。

大多数项目不需要这种抽象级别,因此 DTO 通常是一个实体 class,并从数据访问层一路流向 Controller,在那里它要么被视图使用,要么被发送到 web 浏览器,编码为 JSON。

这取决于项目的规模和复杂性。 项目越大,使每一层尽可能抽象/独立变得越重要。

不同的组织遵循不同的模式。 这取决于您遵循哪种模式。 根据我的个人经验,我遵循以下架构图。

在此处输入图像描述

根据上图,DTO 到实体对话(反之亦然)将仅在服务层内。

一个简化的答案可能是:DTO(如果你需要一个,见下文)是一种允许你将特定信息传输到其他地方的东西。 这是控制器/适配器/存储库/无论你怎么称呼它的任务。 适配器的任务是从外部世界(系统边界之外)获取信息并将这些信息转换为相应的域 model 以便服务逻辑能够使用它。

而且,从我的角度来看,这也适用于存储库:存储库将数据持久化到外部系统(例如数据库或什至另一个 REST 服务)并在请求时将其带回。 为此,它可能需要将域 model 转换为简化的 DTO 以便能够持久保存在目标系统中。

适配器的想法是,业务逻辑不需要知道如何转换 object 以在 REST/SOAP/MySQL/... 协议中表示或传输。 这就是适配器的任务。 因此:如果需要,DTO 应该留在适配器中。

你真的需要 DTO 吗?

DTO 是系统内部数据的另一种抽象。 您还应该考虑是否真的需要它们。 您可能会也可能不会,这取决于您要如何处理这些信息。 如果您使用自己编写查询的数据库来保存数据(这意味着您没有使用 ORM 映射器),您可能根本不需要 DTO,因为您可以直接从域 model 中提取相关信息。

另一方面,如果您对对象使用反序列化器(例如 Jackson 用于 JSON 或类似的东西),您可能会发现自己需要 DTO,因为这些工具有时需要一些特殊要求才能进行序列化和反序列化您的数据到 object 中。 在这里,您可能需要先使用 DTO,然后才能将其转换为域 object,反之亦然。


顺便说一句:这个问题在 softwareengineering.stackexchange.com 上也得到了很好的回答

正确的方法是 Controller -> 服务 -> 实施 -> 存储库

您的存储库层可以返回底层 model,当实现层接收到它时,可以将其转换为您的 DTO。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM