且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

REST API - DTO 与否?

更新时间:2023-11-27 15:49:04

为什么应该在 REST API 中使用 DTO

DTO 代表 Data T传递O对象.

Why you should use DTOs in your REST API

DTO stands for Data Transfer Object.

创建此模式的目的非常明确:将数据传输到远程接口,就像网络服务一样.这种模式非常适合 REST API,从长远来看,DTO 将为您提供更多灵活性.

This pattern was created with a very well defined purpose: transfer data to remote interfaces, just like web services. This pattern fits very well in a REST API and DTOs will give you more flexibility in the long run.

代表应用领域的模型和代表API处理的数据的模型是(或者至少应该是)不同的关注点 并且应该彼此解耦.在应用域模型中添加、删除或重命名字段时,您不希望破坏 API 客户端.

The models that represent the domain of your application and the models that represent the data handled by your API are (or at least should be) different concerns and should be decoupled from each other. You don’t want to break your API clients when you add, remove or rename a field from the application domain model.

虽然您的服务层在域/持久性模型上运行,但您的 API 控制器应该在一组不同的模型上运行.例如,随着您的域/持久性模型发展以支持新的业务需求,您可能希望创建新版本的 API 模型来支持这些更改.您可能还希望在发布新版本时弃用旧版本的 API.并且当事情解耦时完全可以实现.

While your service layer operates over the domain/persistence models, your API controllers should operate over a different set of models. As your domain/persistence models evolve to support new business requirements, for example, you may want to create new versions of the API models to support these changes. You also may want to deprecate the old versions of your API as new versions are released. And it’s perfectly possible to achieve when the things are decoupled.

仅提及公开 DTO 而不是持久性模型的一些好处:

Just to mention a few benefits of exposing DTOs instead of persistence models:

  • 将持久性模型与 API 模型分离.

DTO 可以定制以满足您的需求,它们在仅公开持久性实体的一组属性时非常有用.您不需要诸如 之类的注释@XmlTransient@JsonIgnore 避免某些属性的序列化.

DTOs can be tailored to your needs and they are great when exposing only a set of attributes of your persistence entities. You won't need annotations such as @XmlTransient and @JsonIgnore to avoid the serialization of some attributes.

通过使用 DTO,您将避免在持久性实体中出现地狱般的注释,也就是说,持久性实体不会因​​非持久性相关的注释而变得臃肿.

By using DTOs, you will avoid a hell of annotations in your persistence entities, that is, your persistence entities won't be bloated with non persistence related annotations.

您将完全控制创建或更新资源时收到的属性.

You will have full control over the attributes you are receiving when creating or updating a resource.

如果您使用的是 Swagger,则可以使用 @ApiModel@ApiModelProperty 注释到文档您的 API 模型,而不会弄乱您的持久性实体.

If you are using Swagger, you can use @ApiModel and @ApiModelProperty annotations to document your API models without messing your persistence entities.

您可以为 API 的每个版本使用不同的 DTO.

You can have different DTOs for each version of your API.

映射关系时,您将拥有更大的灵活性.

You'll have more flexibility when mapping relationships.

您可以为不同的媒体类型设置不同的 DTO.

You can have different DTOs for different media types.

您的 DTO 可以拥有 HATEOAS 的链接列表.这是不应该添加到持久性对象的那种东西.当使用 Spring HATEOAS 时,你可以让你的 DTO 类扩展 RepresentationModel(以前称为 ResourceSupport) 或用 EntityModel(以前称为 Resource).

Your DTOs can have a list of links for HATEOAS. That's the kind of thing that shouldn't be added to persistence objects. When using Spring HATEOAS, you can make your DTO classes extend RepresentationModel (formerly known as ResourceSupport) or wrap them with EntityModel (formerly known as Resource<T>).

您无需手动将持久性实体映射到 DTO,反之亦然.您可以使用许多映射框架来做到这一点.例如,看看 MapStruct,它是基于注释的,可用作 Maven 注释处理器.它适用于 CDI 和基于 Spring 的应用程序.

You won't need to map your persistence entities to DTOs and vice versa mannually. There are many mapping frameworks you can use to do it. For instance, have a look at MapStruct, which is annotation based and works as a Maven Annotation Processor. It works well in both CDI and Spring-based applications.

您可能还想考虑使用 Lombok 来生成 getter、setter、equals()hashcode()toString() 方法.

You also may want to consider Lombok to generate getters, setters, equals(), hashcode() and toString() methods for you.

相关:要为您的 DTO 类提供更好的名称,请参阅此答案.

Related: To give better names to your DTO classes, refer to this answer.