什么是数据传输对象?

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


当前回答

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

其他回答

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

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

数据传输对象背后的原理是创建新的数据对象,其中只包括特定数据事务所需的必要属性。

福利包括:

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

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

所有功劳都归里克-安德森所有

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

DTO可用于:

防止over-posting。 隐藏客户端不应该查看的属性。 为了减少有效负载大小,省略一些属性。 扁平化包含嵌套对象的对象图。 扁平化的对象图对客户来说更方便。

DTO方法的实际实现,由rick - anderson在微软Web api最佳教程和实践中使用c#和asp.net Core 5:

一般来说,值对象应该是不可变的。类似于Java中的Integer或String对象。我们可以使用它们在软件层之间传输数据。如果软件层或服务运行在不同的远程节点上,比如在微服务环境中或在遗留的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 |            |
        |------------|         |------------------|                             |------------|

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

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

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

一些ORM框架具有通过使用额外的接口或类进行投影的能力。因此存储库可以直接返回View对象。在那里你不需要额外的转换。

例如,这是我们的User实体:

@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,名,姓。然后,您可以为ORM投影创建一个视图值对象。

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

您可以轻松地从存储库层获得分页结果。多亏了spring,您还可以只使用接口进行投影。

List<UserListItemView> find(Pageable pageable);

不用担心BeanUtils的其他转换操作。复制方法工作得很好。