Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/392.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java RESTAPI-DTOs与否?_Java_Spring_Rest_Dto_Hateoas - Fatal编程技术网

Java RESTAPI-DTOs与否?

Java RESTAPI-DTOs与否?,java,spring,rest,dto,hateoas,Java,Spring,Rest,Dto,Hateoas,我目前正在为一个项目创建一个REST-API,并且一直在阅读关于最佳实践的文章。许多人似乎反对DTO,只是简单地公开了域模型,而其他人似乎认为DTO(或用户模型或任何你想称之为DTO的东西)是不好的做法。我个人认为这很有道理 然而,我也理解DTO的缺点,包括所有额外的映射代码、可能与DTO完全相同的域模型等等 我们的API主要是为了让其他客户端可以使用数据而创建的,但是如果我们做得好,我们也希望在可能的情况下将其用于我们自己的web GUI 问题是,我们可能不想将所有域数据公开给其他客户机用户。

我目前正在为一个项目创建一个REST-API,并且一直在阅读关于最佳实践的文章。许多人似乎反对DTO,只是简单地公开了域模型,而其他人似乎认为DTO(或用户模型或任何你想称之为DTO的东西)是不好的做法。我个人认为这很有道理

然而,我也理解DTO的缺点,包括所有额外的映射代码、可能与DTO完全相同的域模型等等

我们的API主要是为了让其他客户端可以使用数据而创建的,但是如果我们做得好,我们也希望在可能的情况下将其用于我们自己的web GUI

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


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

正如你所说,这显然是一个与意见相关的问题。我自己更喜欢无DTOs方法,这仅仅是因为您需要所有的样板代码

这主要适用于json/RESTAPI的响应端。我甚至编写了一个jackson插件,以避免为这些情况编写许多json视图/过滤器:


另一方面,DTO在此类API的请求输入端是一件好事。例如,考虑到双向关系,直接处理实体可能非常困难。此外,您也不想让调用方修改“creator”属性,例如。因此,在映射此类请求的过程中,需要禁用某些字段

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

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

我倾向于使用DTO

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

域对象的公开可能会导致安全问题和数据泄漏。 Jackson注释似乎可以解决这个问题,但很容易出错并暴露不应该暴露的数据。 在设计DTO类时,犯这样的错误要难得多

另一方面,DTO方法的缺点可以通过像对象到对象映射这样的方法来减少,并且可以减少样板文件。

为什么要在RESTAPI中使用DTO DTO代表

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

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

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


仅提及公开DTO而非持久性模型的几个好处:

  • 将持久性模型与API模型解耦

  • DTO可以根据您的需要进行定制,并且当只公开持久性实体的一组属性时,DTO非常有用。您不需要像和这样的注释来避免某些属性的序列化

  • 通过使用DTO,您将避免持久性实体中的大量注释,也就是说,您的持久性实体不会因为与持久性无关的注释而膨胀

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

  • 如果您正在使用,则可以使用和注释来记录API模型,而不会弄乱持久性实体

  • 对于API的每个版本,您可以有不同的DTO

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

  • 对于不同的媒体类型,您可以有不同的DTO

  • 您的DTO可以具有的链接列表。这是不应该添加到持久性对象中的东西。使用时,可以使DTO类扩展(以前称为)或使用(以前称为)包装它们

处理样板代码 您不需要手动将持久性实体映射到DTO,反之亦然。你可以用它来做这件事。例如,看一看,它是基于注释的,作为Maven注释处理器工作。它在CDI和基于Spring的应用程序中都运行良好

您还可以考虑生成GETTER、SETTER、<代码>均衡器()/<代码>、<代码> HASCODE()<<代码>和<代码> toSTRIN()/<代码>方法。< /P>



相关:要给您的DTO类起更好的名字,请参考此项。

我同意我的问题是这样的