DTO(Data Transfer Object,数据传输对象)
DTO(Data Transfer Object,数据传输对象) 是一种软件设计模式中的概念,主要用于在不同层或不同系统之间安全、高效地传输数据。
🧩 核心目的
解耦 + 精简 + 安全
- 避免直接暴露内部实体(Entity)或数据库模型;
- 只传输需要的数据字段,减少网络负载;
- 防止敏感信息(如密码、内部状态)被意外泄露;
- 适配不同接口的返回格式需求。
📦 举个例子(以用户系统为例)
1. 数据库中的实体(Entity)
ts
// UserEntity(包含所有字段,甚至敏感信息)
class UserEntity {
id: number;
username: string;
email: string;
passwordHash: string; // ❌ 敏感!不能直接返回给前端
createdAt: Date;
updatedAt: Date;
}2. 前端需要的用户信息(DTO)
ts
// UserDTO(只包含安全、必要的字段)
interface UserDTO {
id: number;
username: string;
email: string; // ✅ 安全字段
// 没有 passwordHash!
}3. 在 API 中使用
ts
// Controller
app.get('/user/:id', (req, res) => {
const user = userService.findById(req.params.id); // 返回 UserEntity
const dto: UserDTO = {
id: user.id,
username: user.username,
email: user.email
};
res.json(dto); // ✅ 只返回 DTO
});🔁 DTO 的常见场景
| 场景 | 说明 |
|---|---|
| 前后端通信 | 后端返回给前端的数据结构(避免暴露 DB 字段) |
| 微服务间调用 | 服务 A 调用服务 B,通过 DTO 传递参数或结果 |
| API 版本兼容 | v1 和 v2 接口返回不同 DTO,但底层 Entity 不变 |
| 请求参数校验 | 使用 CreateUserDTO 接收前端提交的数据,并做验证 |
请求 DTO 示例(输入)
ts
// CreateUserDTO(用于接收注册请求)
interface CreateUserDTO {
username: string;
email: string;
password: string; // 前端传明文,后端加密存储
}✅ DTO 的优点
- 安全性:不暴露内部实现细节(如数据库主键策略、敏感字段);
- 灵活性:同一实体可对应多个 DTO(如
UserPublicDTO、UserAdminDTO); - 可维护性:修改数据库结构不影响 API 接口(只要 DTO 不变);
- 序列化友好:DTO 通常是 plain object,易于 JSON 转换。
⚠️ 注意事项
- DTO 不应包含业务逻辑,它只是“数据容器”;
- 不要为了 DTO 而过度设计——简单项目可直接用 Entity(但需谨慎);
- 在 TypeScript/Java 等强类型语言中,DTO 通常定义为
interface或class(无方法)。
🌐 在不同技术栈中的体现
| 技术栈 | DTO 实践 |
|---|---|
| NestJS(Node.js) | 使用 class-validator + class-transformer 定义 DTO |
| Spring Boot(Java) | 常见 UserDto.java,配合 @RequestBody / @ResponseBody |
| .NET | 使用 Record 或 Class 定义 DTO,配合 AutoMapper 映射 |
| Vue/React 前端 | 通常用 TypeScript interface 描述 API 返回的数据结构(这也是一种 DTO) |
💡 一句话总结
DTO 就是你“愿意给别人看的数据样子”,而不是你“自己存的数据样子”。
如果你在写 API,建议始终通过 DTO 与外界交互,这是专业后端开发的常见实践 ✅。
