REST API - 是否使用DTO?[已关闭]

16 浏览
0 Comments

REST API - 是否使用DTO?[已关闭]

已关闭。这个问题是基于观点的。目前不接受回答。


想改进这个问题? 更新这个问题使其能够通过事实和引用回答。

改进这个问题

我目前正在为一个项目创建REST-API,并一直在阅读有关最佳实践的文章。许多人似乎反对DTO,只是暴露领域模型,而另一些人似乎认为DTO(或用户模型或任何你想称之为的东西)是不好的实践。就个人而言,我觉得这篇文章很有道理。

然而,我也理解DTO的缺点,包括所有额外的映射代码、与其DTO对应物可能百分之百相同的领域模型等。

我们的API主要是为其他客户端消费数据而创建的,然而,如果我们做得正确,我们也希望在可能的情况下将其用于我们自己的Web GUI。

问题是,我们可能不希望向其他客户端用户公开所有领域数据。许多数据只在我们自己的Web应用程序中有意义。此外,在所有情况下,我们可能不想公开有关对象的所有数据,特别是与其他对象的关系等。例如,如果我们公开特定对象的列表,我们不一定希望公开整个对象层次结构。因此,对象的子级不会被公开,但可以通过链接(HATEOAS)发现。

我应该如何解决这个问题?我在思考在我们的域模型上使用Jackson mixins来控制在不同场景下公开哪些数据。还是我们应该一直使用DTO - 即使它有缺点和争议?

admin 更改状态以发布 2023年5月24日
0
0 Comments

\n\n当你的API是公共的并且你必须支持多个版本时,你必须使用DTOs。\n\n另一方面,如果这是私有API并且你控制客户端和服务器,我倾向于跳过DTOs并直接暴露领域模型。

0
0 Comments

为什么你应该在你的REST API中使用DTOs

DTO代表Data Transfer Object

这一模式具有非常明确定义的目的:传输数据到远程界面,就像Web服务一样。这一模式非常适合REST API,使用DTOs将在长远来看给你更多的灵活性。

表示应用程序域的模型与表示API处理的数据的模型是(或至少应该是)不同的问题,并且应该相互解耦。您不希望在应用程序域模型中添加、删除或重命名字段时破坏API客户端。

当您的服务层操作域/持久性模型时,您的API控制器应该操作不同的模型集。当您的域/持久性模型发展到支持新的业务要求时,例如,您可能希望创建新版本的API模型以支持这些变化。随着新版本的推出,您可能还希望取消旧版本的API。这是完全可能的,当这些事情相互解耦时。


只是提一下使用DTOs暴露而不是持久性模型的一些好处:

  • 将持久性模型从API模型中解耦。

  • DTOs可以根据您的需求定制,并且当仅公开持久性实体的一组属性时非常有用。您不需要使用@XmlTransient@JsonIgnore等注释来避免一些属性的序列化。

  • 使用DTOs可以避免您的持久性实体中的注释过多,也就是说,您的持久性实体不会因非持久性相关注释而变得臃肿。

  • 在创建或更新资源时,您将完全控制您接收到的属性。

  • 如果您正在使用Swagger,您可以使用@ApiModel@ApiModelProperty注释来记录您的API模型,而不会影响您的持久性实体。

  • 您可以为每个API版本使用不同的DTOs。

  • 在映射关系时,您将拥有更多的灵活性。

  • 您可以为不同的媒体类型使用不同的DTOs。

  • 您的DTOs可以有一个链接列表,用于HATEOAS。这种事情不应该添加到持久对象中。当使用Spring HATEOAS时,您可以使您的DTO类扩展RepresentationModel(以前称为ResourceSupport)或使用EntityModel(以前称为Resource)来包装它们。

处理模板代码

您将不需要手动将您的持久性实体映射到DTOs,反之亦然。有许多映射框架可以用来完成此操作。例如,看看基于注释的MapStruct,它作为Maven注释处理器工作。它在基于CDI和Spring的应用程序中都能很好地工作。

你也可以考虑使用Lombok来为你生成getter,setter,equals()hashcode()toString()方法。


相关:要为你的DTO类取更好的名称,请参考这个答案

0