1. DTO
数据传输对象(DTO, Data Transfer Object)是一种设计模式,用于在不同系统或应用层之间封装和传输数据。它通常用于解耦领域模型(如数据库实体)和外部接口(如API请求/响应),避免直接暴露内部数据结构,同时优化网络传输效率。
1. DTO的核心作用
- 数据封装:将多个数据字段组合成一个对象,减少网络请求次数。
- 安全性:隐藏领域模型的敏感字段(如数据库ID、密码等)。
- 适配接口:为不同场景定制数据结构(如不同的API版本或客户端需求)。
- 性能优化:减少传输数据量,避免传输冗余字段。
2. DTO的结构特点
- 简单无逻辑:仅包含字段、Getter/Setter方法,没有业务逻辑。
- 序列化支持:通常可序列化为JSON/XML等格式,方便网络传输。
3. DTO vs 实体类(Entity)
特性 | DTO | 实体类 |
---|---|---|
用途 | 数据传输 | 映射数据库表结构 |
生命周期 | 短生命周期(仅用于传输) | 长生命周期(与数据库交互) |
字段暴露 | 仅暴露必要字段 | 包含完整数据库字段 |
校验逻辑 | 包含接口层校验注解(如@Email) | 包含业务逻辑校验 |
4. DTO的典型使用场景
- API请求参数:接收前端提交的表单或JSON数据。
- API响应结果:返回给前端的结构化数据(排除敏感字段 )。
- 微服务间通道:服务间通过DTO传递数据,而非直接暴露领域模型。
- 批量操作:封装批量处理的数据集合。
5. DTO设计示例
场景:用户注册接口
- 请求DTO:接收用户名、密码、邮箱
- 响应DTO:返回用户ID、用户名、注册时间(排除密码字段)
代码示例:
// 请求DTO:接收用户注册数据(包含校验注解)
public class UserRegisterRequest {@NotBlank(message = "用户名不能为空")@Size(min = 3, max = 20, message = "用户名长度需在3-20位")private String username;@NotBlank(message = "密码不能为空")@Size(min = 6, max = 20, message = "密码长度需在6-20位")private String password;@Email(message = "邮箱格式不正确")private String email;// Getters and Setters
}// 响应DTO:返回注册结果
public class UserRegisterResponse {private Long userId;private String username;private LocalDateTime registerTime;// Getters and Setters
}
2. 常见问题
1. DTO与Entity字段不一致怎么办?
通过转换工具或手动代码映射字段,例如:
public class UserMapper {public static UserRegisterResponse toResponse(User user) {UserRegisterResponse response = new UserRegisterResponse();response.setUserId(user.getId());response.setUsername(user.getUsername());return response;}
}
2. DTO需要实现序列化吗?
如果用于网络传输(如RPC调用),建议实现Serializable接口。
3. 如何复用DTO?
- 通过继承:定义基础DTO扩展出具体场景的DTO
- 通过组合:将公共字段封装为独立的DTO类,再通过引用组合使用。