什么是数据传输对象?

Yar*_*veh 186 architecture model-view-controller data-transfer data-transfer-objects dto

什么是数据传输对象?

在MVC中是模型类DTO,如果没有,有什么不同,我们是否需要两者?

Ben*_*ett 194

数据传输对象是一个对象,用于封装数据,并将其从应用程序的一个子系统发送到另一个子系统.

DTO最常用于N层应用程序中的服务层,用于在自身和UI层之间传输数据.这里的主要好处是它减少了需要在分布式应用程序中通过线路发送的数据量.他们还在MVC模式中创造了很好的模型.

DTO的另一个用途是封装方法调用的参数.如果方法需要4个或5个以上的参数,这将非常有用.

使用DTO模式时,您还可以使用DTO组装器.汇编程序用于从域对象创建DTO,反之亦然.

从域对象到DTO的转换再返回可能是一个代价高昂的过程.如果您没有创建分布式应用程序,那么您可能不会从该模式中看到任何好处,正如Martin Fowler在此解释的那样

  • "DTO的另一个用途是封装方法调用的参数.如果一个方法需要超过4或5个参数,这将非常有用." 这实际上是一种反模式,叫做Poltergeist或Gypsy Wagon类.如果你的方法需要4个参数然后给它4,不要只是为了将对象移动到方法或类中而创建一个类. (10认同)
  • "DTO在MVC模式中创建了很好的模型" - 但是模型不应该包含对象的所有数据,并且DTO应该使用部分数据进行优化吗?如果我有模型A而我需要将它传递给两个子系统,那么会有A_DTO_1和A_DTO_2以及每个子系统的相关字段吗?"DTO可以封装方法调用的参数" - >所以包装参数的每个类都是DTO,即使这不是分布式系统?MVC中的模型不是域对象吗? (6认同)
  • DTO不应该用于封装方法调用的参数(这将使它们成为LocalDTO),它们是在远程接口的上下文中引入的:http://martinfowler.com/bliki/LocalDTO.html (3认同)
  • @Wix a [poltergeist](https://sourcemaking.com/antipatterns/poltergeists) 几乎与参数对象(或 DTO)相反。吵闹鬼是无状态的,而参数对象或 DTO 只是状态。 (3认同)
  • 在回答你的第一个问题时,我认为不是在谈论同样的事情.MVC中的模型不一定需要是域模型中的类.话虽如此,它可能是.使用DTO去除所有不必要的东西.只是取决于你想要的架构.我不确定如何回答你的第二个问题.无论是否跨越线路,它仍然是一个对象,它封装了一系列要在(子)系统之间传输的数据,所以我认为它是一个DTO. (2认同)
  • @Wix,好点。但是,我认为如果它在语义上是正确的(例如,如果您传递带有属性的设置类而不是将属性本身作为值),这是可以的。您不应该为了传递单个对象而将所有参数都放入,因为它们很可能是不相关的,并且会在以后引起恶梦。 (2认同)

blu*_*blu 24

DTO的定义可以在Martin Fowler的网站上找到.DTO用于将参数传递给方法和返回类型.很多人在UI中使用它们,但是其他人从它们中膨胀域对象.


Eri*_*lje 19

DTO是一个愚蠢的对象 - 它只包含属性并具有getter和setter,但没有任何其他逻辑(除了compare()或equals()实现之外).

通常,MVC中的模型类(假设.net MVC在这里)是DTO,或DTO的集合/聚合

  • 您所描述的是 LocalDTO:http://martinfowler.com/bliki/LocalDTO.html (4认同)
  • 如果您在表示层中的模型与基础域模型之间存在显着不匹配,则使用DTO之类的有用的一种情况.在这种情况下,使表示特定的外观/网关从域模型映射并呈现便于演示的界面是有意义的. (2认同)

Ali*_*rat 13

所有功劳归于瑞克·安德烈森 (Rick-Andreson)

生产应用程序通常会使用模型的子集来限制输入和返回的数据。这背后有多种原因,其中安全是一个主要原因。模型的子集通常称为数据传输对象( DTO )、输入模型或视图模型。

DTO 可用于 PHOFF:

  • 防止过度发帖。
  • 隐藏客户端不应查看的属性。
  • 省略一些属性以减少有效负载大小。
  • 展平包含嵌套对象的对象图。
  • 扁平化的对象图对客户来说会更方便。

DTO 方法的实际实现,作者:Rick-Andreson,关于使用 C# 和 ASP .Net Core 5 的Microsoft Web API 最佳教程和实践:


Fır*_*ÇÜK 10

通常,Value Objects应该是Immutable.与Java中的IntegerString对象类似.我们可以使用它们在软件层之间传输数据.如果软件层或服务在不同的远程节点中运行,例如在微服务环境或旧版Java Enterprise App中运行.我们必须制作两个类的几乎完全相同的副本.这是我们遇到DTO的地方.

|-----------|                                                   |--------------|
| SERVICE 1 |--> Credentials DTO >--------> Credentials DTO >-- | AUTH SERVICE |
|-----------|                                                   |--------------|
Run Code Online (Sandbox Code Playgroud)

在传统的Java Enterprise Systems中,DTO可以包含各种EJB内容.

我不知道这是一个最佳实践,但我个人在我的Spring MVC/Boot项目中使用Value Objects,如下所示:

        |------------|         |------------------|                             |------------|
-> Form |            | -> Form |                  | -> Entity                   |            |
        | Controller |         | Service / Facade |                             | Repository |
<- View |            | <- View |                  | <- Entity / Projection View |            |
        |------------|         |------------------|                             |------------|
Run Code Online (Sandbox Code Playgroud)

控制器层不知道实体是什么.它与表单视图值对象进行通信.表单对象具有JSR 303验证注释(例如@NotNull)和视图值对象具有用于自定义序列化的Jackson注释.(例如@JsonIgnore)

服务层通过使用实体对象与存储库层进行通信.实体对象上有JPA/Hibernate/Spring Data注释.每个层仅与下层通信.由于循环/循环依赖性,禁止层间通信.

User Service ----> XX CANNOT CALL XX ----> Order Service
Run Code Online (Sandbox Code Playgroud)

某些ORM框架具有使用其他接口或类进行投影的能力.因此,存储库可以直接返回View对象.因为你不需要额外的转换.

例如,这是我们的用户实体:

@Entity
public final class User {
    private String id;
    private String firstname;
    private String lastname;
    private String phone;
    private String fax;
    private String address;
    // Accessors ...
}
Run Code Online (Sandbox Code Playgroud)

但是你应该返回一个仅包含id,firstname,lastname的Paginated用户列表.然后,您可以为ORM投影创建视图值对象.

public final class UserListItemView {
    private String id;
    private String firstname;
    private String lastname;
    // Accessors ...
}
Run Code Online (Sandbox Code Playgroud)

您可以轻松地从存储库层获取分页结果.感谢spring,你也可以只使用接口进行投影.

List<UserListItemView> find(Pageable pageable);
Run Code Online (Sandbox Code Playgroud)

不要担心其他转换操作BeanUtils.copy方法工作正常.


Thi*_*gos 8

1)对我来说,问题的最佳答案是什么是DTO是DTO是简单的对象,不应包含任何需要测试的业务逻辑或方法实现.

2)通常你的模型(使用MVC模式)是智能模型,它们可以包含许多/某些方法,专门为该模型执行一些不同的操作(不是业务逻辑,这应该在控制器上).但是,当您传输数据(例如,从某个地方调用REST(GET/POST /无论)端点,或使用soa等消费Web服务时),您不希望使用非代码传输大型对象端点所必需的,将消耗数据,并减慢传输速度.

  • @Thiago Burgos 你的意思是“在服务中”吗? (2认同)

小智 7

数据传输对象背后的原则是创建仅包含特定数据事务所需的必要属性的新数据对象。

好处包括:

使数据传输更安全 如果删除所有不必要的数据,请减少传输大小。

了解更多: https: //www.codenerd.co.za/what-is-data-transfer-objects


Dan*_*Dan 6

使用MVC数据传输对象通常用于将域模型映射到最终将由视图显示的更简单的对象.

来自维基百科:

数据传输对象(DTO),以前称为值对象或VO,是用于在软件应用程序子系统之间传输数据的设计模式.DTO通常与数据访问对象结合使用,以从数据库中检索数据.

  • 值对象不是[DTO](https://en.wikipedia.org/wiki/Data_transfer_object)。 (2认同)

小智 5

一些程序员使用 DTO 来区分将通过 API 传递的最终对象数据。因此,它基本上是端点的有效负载对象。例如,您可以将传递给服务器的联系表单值对象命名为contactFormDto or contactFromPayload,然后您或任何其他程序员都知道该对象中的内容是数据的最终形状,它将通过网络传输。