为了账号安全,请及时绑定邮箱和手机立即绑定

REST API - DTO或不是?

/ 猿问

REST API - DTO或不是?

浮云间 2019-08-09 16:17:44

REST API - DTO或不是?

我目前正在为一个项目创建一个REST-API,并且正在阅读关于最佳实践的文章。许多人似乎反对DTO,只是暴露域模型,而其他人似乎认为DTO(或用户模型或任何你想称之为的)是不好的做法。就个人而言,我认为这篇文章很有意义。

但是,我也理解DTO的缺点,包括所有额外的映射代码,可能与其DTO对应物100%相同的域模型等等。

我们的API主要是为了让其他客户端可以使用数据而创建的,但是如果我们做得对,我们也希望尽可能将它用于我们自己的Web GUI。

问题是我们可能不希望将所有域数据公开给其他客户端用户。大部分数据只在我们自己的Web应用程序中才有意义。此外,我们可能不希望在所有方案中公开有关对象的所有数据,尤其是与其他对象的关系等。例如,如果我们公开特定对象的列表,我们不一定要暴露整个对象层次结构; 这样对象的孩子就不会暴露,但可以通过链接(hateoas)发现。

我该如何解决这个问题?我正在考虑在我们的域模型上使用Jackson mixins来控制在给定不同场景的情况下会暴露哪些数据。或者我们应该一直使用DTO - 即使考虑到它的缺点和争议?


查看完整描述

3 回答

?
料青山看我应如是

为什么要在REST API中使用DTO

DTO代表D ata T ransfer O bject

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

代表您的应用程序的模型以及代表API处理数据的模型是(或至少应该是)不同的关注点,并且应该彼此分离。在应用程序域模型中添加,删除或重命名字段时,您不希望破坏API客户端。

当您的服务层在域/持久性模型上运行时,您的API控制器应该在不同的模型集上运行。例如,当您的域/持久性模型发展为支持新的业务需求时,您可能希望创建新版本的API模型以支持这些更改。在新版本发布时,您可能还想弃用旧版本的API。当事物分离时,完全有可能实现。


只是提到暴露DTO而不是持久性模型的一些好处:

  • 从API模型中去除持久性模型。

  • DTO可以根据您的需求进行定制,并且在仅暴露持久性实体的一组属性时它们非常棒。您不需要注释,例如@XmlTransient@JsonIgnore避免某些属性的序列化。

  • 通过使用DTO,您将避免在持久性实体中出现一些注释,也就是说,持久性实体不会因非持久性相关注释而膨胀。

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

  • 如果您使用的是Swagger,则可以使用@ApiModel@ApiModelProperty注释来记录API模型,而不会弄乱持久性实体。

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

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

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

  • 您的DTO可以包含HATEOAS的链接列表。这是不应该添加到持久性对象的那种东西。使用Spring HATEOAS时,可以使DTO类扩展ResourceSupport或包装它们Resource<T>

处理样板代码

你不会需要你的持久实体反之亦然映射到DTO的副码的手动。有很多映射框架,你可以用它来做到这一点。例如,看看MapStruct,它是基于注释的,并作为Maven注释处理器。它适用于CDI和基于Spring的应用程序。

您可能还需要考虑龙目岛生成getter,setter方法,equals()hashcode()toString()为你的方法。


查看完整回答
反对 回复 2019-08-09
?
幕布斯5086720

当您的API是公开的并且您必须支持多个版本时,您必须使用DTO。

另一方面,如果它是私有API并且您同时控制客户端和服务器,我倾向于跳过DTO并直接暴露域模型。


查看完整回答
反对 回复 2019-08-09
?
尚方宝剑之说

我倾向于使用DTO。

我不喜欢这些缺点,但似乎其他选择更糟糕:

域对象的展示可能会导致安全问题和数据泄漏。杰克逊的注释似乎可以解决这个问题,但是很容易犯错误并暴露不应该暴露的数据。在设计DTO课程时,犯这样的错误要困难得多。

另一方面,DTO方法的缺点可以通过对象映射和Lombok等较少的样板来减少。


查看完整回答
反对 回复 2019-08-09

添加回答

回复

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信