336

什么是数据传输对象?

在 MVC 中是模型类 DTO,如果不是,有什么区别,我们需要两者吗?

4

12 回答 12

326

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

DTO 最常被 N 层应用程序中的服务层用于在其自身和 UI 层之间传输数据。这里的主要好处是它减少了分布式应用程序中需要通过网络发送的数据量。他们还在 MVC 模式中制作了出色的模型。

DTO 的另一个用途是封装方法调用的参数。如果一个方法需要四个或五个以上的参数,这会很有用。

使用 DTO 模式时,您还将使用 DTO 汇编器。汇编器用于从域对象创建 DTO,反之亦然。

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

于 2009-06-29T13:09:41.540 回答
40

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

于 2009-06-26T20:43:28.333 回答
36

DTO 是一个愚蠢的对象 - 它只包含属性并具有 getter 和 setter,但没有其他任何重要的逻辑(可能除了 a compare()orequals()实现)。

通常 MVC 中的模型类(假设此处为 .net MVC)是 DTO,或 DTO 的集合/聚合

于 2009-06-26T20:44:46.303 回答
25

一般来说,值对象应该是不可变的。就像Java 中的IntegerString对象。我们可以使用它们在软件层之间传输数据。如果软件层或服务在不同的远程节点中运行,例如在微服务环境或旧版 Java 企业应用程序中。我们必须几乎完全复制两个类。这就是我们遇到 DTO 的地方。

|-----------|                                                   |--------------|
| SERVICE 1 |--> Credentials DTO >--------> Credentials DTO >-- | AUTH SERVICE |
|-----------|                                                   |--------------|

在遗留 Java 企业系统中,DTO 可以包含各种 EJB 内容。

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

        |------------|         |------------------|                             |------------|
-> Form |            | -> Form |                  | -> Entity                   |            |
        | Controller |         | Service / Facade |                             | Repository |
<- View |            | <- View |                  | <- Entity / Projection View |            |
        |------------|         |------------------|                             |------------|

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

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

User Service ----> XX CANNOT CALL XX ----> Order Service

一些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 ...
}

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

public final class UserListItemView {
    private String id;
    private String firstname;
    private String lastname;
    // Accessors ...
}

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

List<UserListItemView> find(Pageable pageable);

不要担心其他转换操作BeanUtils.copy方法工作得很好。

于 2012-10-27T18:06:35.227 回答
17
  1. 对我来说,什么是 DTO问题的最佳答案是DTO是简单的对象,不应该包含任何需要测试的业务逻辑或方法实现
  2. 通常,您的模型(使用 MVC 模式)是智能模型,它们可以包含许多/一些方法,专门为该模型执行一些不同的操作(不是业务逻辑,这应该在控制器中)。但是,当您传输数据(例如,从某处调用 REST(GET// POSTwhatever)端点,或使用 SOA 使用 Web 服务等)时,您不希望使用不必要的代码传输大型对象端点,将消耗数据,并减慢传输速度。
于 2015-03-18T12:52:18.770 回答
9

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

来自维基百科

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

于 2009-06-26T20:41:46.170 回答
4

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

好处包括:

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

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

于 2021-02-16T19:34:25.780 回答
4

所有学分都归功于Rick-Andreson

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

DTO 可用于:

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

DTO 方法的实际实现,Rick-AndresonMicrosoft Web APIs best tutorials and practice using C# and ASP .Net Core 5 上:

于 2021-04-19T21:13:41.587 回答
1

数据传输对象 (DTO) 描述了“在进程之间传输数据的对象”(维基百科)或“用于封装数据并将其从应用程序的一个子系统发送到另一个子系统的对象”(堆栈溢出答案)。

于 2020-03-03T17:10:01.960 回答
1

我会向我的孩子解释 DTO

我的儿子,数据传输对象(又名 DTO)**用于封装我们从一个端点发送到另一个端点的数据。使用 DTO 为系统中的端点定义输入和输出接口

在这种情况下,将系统视为端点的集合。端点可以是相互通信的(移动应用程序、Web 应用程序、后端 API)之间的任何东西。

于 2021-03-13T12:02:18.270 回答
1

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

于 2021-12-17T06:28:57.487 回答
0

定义

DTO 是硬编码的数据模型。它只解决了对由硬编码生产过程处理的数据记录进行建模的问题,其中所有字段在编译时都是已知的,因此可以通过强类型属性进行访问。

相反,动态模型或“属性包”解决了在运行时创建生产过程时对数据记录进行建模的问题。

Cvar

DTO 可以用字段或属性建模,但有人发明了一个非常有用的数据容器,称为 Cvar。它是对值的引用。当 DTO 使用我称之为引用属性的东西建模时,可以将模块配置为共享堆内存,从而协作处理它。这完全消除了代码中的参数传递和 O2O 通信。换句话说,具有引用属性的 DTO 允许代码实现零耦合

    class Cvar { ... }

    class Cvar<T> : Cvar
    {
        public T Value { get; set; }
    }

    class MyDTO
    {
        public Cvar<int> X { get; set; }
        public Cvar<int> Y { get; set; }
        public Cvar<string> mutableString { get; set; } // >;)
    }

资料来源: http ://www.powersemantics.com/

动态 DTO 是动态软件的必要组件。为了实例化一个动态过程,一个编译器步骤是将脚本中的每台机器绑定到脚本定义的引用属性。通过将 Cvar 添加到集合中来构建动态 DTO。

    // a dynamic DTO
    class CvarRegistry : Dictionary<string, Cvar> { }

争论

注意:因为 Wix 将使用 DTO 组织参数标记为“反模式”,所以我将给出权威意见。

    return View(model);  // MVC disagrees

我的协作架构取代了设计模式。参考我的网络文章。

参数提供对堆栈帧机器的直接控制。如果您使用连续控制,因此不需要立即控制,则您的模块不需要参数。我的架构没有。当参数是值类型时,机器(方法)的进程内配置增加了复杂性,但也增加了价值(性能)。但是,引用类型参数会使消费者导致缓存未命中以从堆中获取值——因此,只需使用引用属性配置消费者。来自机械工程的事实:依赖参数是一种预优化,因为加工(制造部件)本身就是浪费。有关详细信息,请参阅我的 W 文章。http://www.powersemantics.com/w.html

如果 Fowler 和公司了解任何其他架构,他们可能会意识到 DTO 在分布式架构之外的好处。程序员只知道分布式系统。集成协作系统(又名生产又名制造)是我不得不声称自己的架构,因为我是第一个以这种方式编写代码的人。

有些人认为 DTO 是一个贫乏的领域模型,这意味着它缺乏功能,但这假设一个对象必须拥有它与之交互的数据。然后,这个概念模型迫使您在对象之间传递数据,这是分布式处理的模型。然而,在生产线上,每个步骤都可以访问最终产品并对其进行更改,而无需拥有或控制它。这就是分布式处理和集成处理之间的区别。制造将产品与运营和物流分开。

将处理建模为一群无用的办公室工作人员,他们在不保留电子邮件跟踪的情况下相互发送工作邮件,这在本质上没有任何问题,除了在处理物流和退货问题时产生的所有额外工作和头痛。一个正确建模的分布式流程将一个文档(主动路由)附加到产品上,描述它来自和将去往的操作。活动路由是流程源路由的副本,它是在流程开始之前编写的。如果发生缺陷或其他紧急更改,则修改活动路由以包括将发送到的操作步骤。这说明了投入生产的所有劳动力。

于 2020-04-17T16:13:56.060 回答