DTO 类和 VO 类实战指南:如何高效构建数据传输模型

在微服务架构、RESTful API 开发以及前端交互场景中,DTO(Data Transfer Object)和VO(View Object)是构建安全、高效数据流组件。它们分别解决了“数据如何被接收与处理”和“数据如何被展示”的问题。
这篇文章将深入解析两者的定义、应用场景、设计原则,并提供具体的代码示例与数据说明表格。
核心概念解析
DTO (Data Transfer Object)
全称:数据传输对象。 核心职责:负责将业务数据从后端系统(如数据库、业务逻辑层)安全地传输到前端或其他外部系统(如短信网关、支付接口)。 关注点:数据的完整性、业务领域规则、安全性。 典型场景: 将数据库中的用户信息发送至前端页面。 将订单数据发送给支付网关。 将监控指标发送给运维大屏。VO (View Object)
全称:视图对象。 核心职责:负责将展示数据从后端传输到前端,确保前端能以最友好的方式呈现信息。 关注点:数据的可读性、展示友好性、去重、隐藏敏感字段。 典型场景: 将用户信息映射到 `UserForm` 表单。 将订单详情展示在购物车列表中。 将用户画像数据对接到营销弹窗。核心区别与对比
| 维度 | DTO (数据传输对象) | VO (视图对象) |
|---|---|---|
| 关键目的 | 保证数据从业务系统安全、完整传输 | 保证数据在用户界面友好、易读 |
| 数据来源 | 后端业务数据 (数据库/业务层) | 后端业务数据 (经过筛选/格式化) |
| 数据展示 | 无展示功能,首要作为传递载体 | 提供字段展示,可绑定表单/视图 |
| 安全性 | 关注输入校验、反序列化安全 | 关注展示隐私、敏感字段脱敏 |
| 业务限制 | 强 (必须包含所有业务数据) | 弱 (可省略、合并、格式化) |
| 典型用途 | 写入接口、外部系统调用、数据接收 | 前端表单、列表渲染、弹窗展示 |
设计原则与最佳实践
DTO 设计原则
业务语义化:字段命名应反映业务含义(如 `user_id` 优于 `id`)。 必填性明确:使用 `@NotNull` 等注解明确哪些字段是必填的。 层级清晰:避免嵌套过深,凭借 Map 或 List 传递复杂结构,便于前端解构。 可选值丰富:支持全部字段、部分字段、全部字段 + 默认值的组合。VO 设计原则
展示优先:字段命名应侧重于展示(如 `userName` 优于 `name`)。 隐私保护:对于登录态、密码、身份证号等敏感字段,必须采用 `@JsonProperty("脱敏字段")` 或自定义注解进行脱敏。 简洁性:VO 常用于传递前端直接展示的部分,不须要严格的业务校验,但需确保逻辑正确。 灵活性:支持省略字段,允许前端动态生成页面。代码实战示例
场景:用户注册与登录流程
假设我们有一个 `User` 实体,我们需分别设计用于接收登录请求的 DTO 和用于展示用户信息的 VO。
1. DTO 示例:用户登录请求
此对象用于接收前端传来的登录数据,确保数据格式符合后端规范。```java
public class LoginDTO {
// 标准必填字段
private Long userId;

// 可选字段,用于记住登录状态
private String rememberMe;
// 可选字段,用于 JWT Token
private String token;
// 可选字段,用于找回密码
private String password;
public LoginDTO() {
}
public LoginDTO(Long userId) {
this.userId = userId;
}
// Getter & Setter
public Long getUserId() { return userId; }
public void setUserId(Long userId) { this.userId = userId; }
// ...
}
```
2. VO 示例:用户列表展示
此对象用于在列表页展示用户信息,去除隐私字段并开展格式化。```java
public class UserVO {
// 展示用字段
private Long id;
private String name;
private String phone;
private String avatarUrl;
// 敏感信息,默认脱敏
private String password; // @JsonProperty("密码")
private String email; // @JsonProperty("邮箱")
// 默认值
private static final String DEFAULT_NAME = "匿名用户";
private static final String DEFAULT_PHONE = "未设置";
public Long getId() { return id; }
public void setId(Long id) { this.id = id; }
// ...
}
```
数据说明与验证
在实际开发中,数据验证是防止 Bug 。以下是具体的数据验证策略说明:
DTO 数据验证策略
前端校验:在 `@RequestBody` 注解上利用 `@NotBlank`, `@NotEmpty`, `@Email` 等注解开展初步校验。 后端校验:在 Controller 或 Service 层进行二次校验,确保符合业务规则(如:手机号格式必须正确,身份证号必须为 18 位)。 安全校验:对特殊字符(如 `@`, `#`, `$`)进行白名单校验,防止注入攻击。VO 数据展示策略
脱敏处理:根据数据关键性,对敏感字段(如手机号一位、身份证号中间位)实施掩码处理。 示例:`1380000` 默认值填充:对于 `null` 或空值字段,直接返回默认字符串,避免前端显示 "null" 或报错。 JSON 格式化:在 VO 中配置 JSON 序列化器,控制字段显示顺序,避免冗长的字段名。总结
DTO 类是数据的守门员,它确保了业务逻辑的严谨性和数据传输的安全性;而 VO 类是数据的展示官,它赋予了数据人性化的表达形式。
在架构设计中,切勿混淆两者。开发者应时刻思考:“这个字段是为了接收业务数据(DTO),还是为了展示给用户(VO)?”
经过合理运用注解(如 `@NotNull`, `@JsonProperty`)和编写良好的代码逻辑,我们不仅能构建出健壮的后端服务,还能提供很好的开发者体验和用户感知。





