dto是专为接口设计的数据“信封”,用于对外暴露时隐藏内部结构、仅传递必要字段。它不同于entity和vo,需按场景拆分、严格过滤敏感字段,并在controller层收发、service层转换。

对外暴露接口时用 DTO,核心是把内部数据结构“藏起来”,只按接口契约传递必要字段,既安全又可控。
明确 DTO 的定位和边界
DTO 不是数据库实体(Entity)的复制品,也不是前端直接能用的视图对象(VO),它是专为某个接口设计的数据“信封”。比如一个用户查询接口只返回 ID、昵称、头像和注册时间,那就只在 UserDTO 里定义这四个字段,其他一概不加。字段命名可与前端约定一致(如 user_name 而非 userName),避免额外转换。
在 Controller 层收发都走 DTO
前端提交数据时,用 DTO 接收;后端返回数据时,也用 DTO 封装。Spring Boot 中可直接作为 @RequestBody 或 @ResponseBody 参数:
- 接收:@PostMapping("/users") public Result
createUser(@RequestBody UserCreateDTO dto) - 返回:@GetMapping("/users/{id}") public Result
getUser(@PathVariable Long id)
这样 Controller 不依赖 Entity,也不暴露任何内部模型细节。
Service 层负责 Entity 与 DTO 的双向转换
转换逻辑不要写在 Controller 或 Mapper 中,统一放在 Service 层或专用的 Converter 工具类里。推荐使用 MapStruct 或 ModelMapper 等工具自动生成映射代码,减少手写错误。例如:
- User user = userMapper.selectById(id);
- UserDetailDTO dto = UserDetailDTO.from(user); // 静态工厂方法
- 或 UserDetailDTO dto = userDetailConverter.toDto(user);
敏感字段(如 password、salt、deleted_flag)必须过滤,不能出现在任何对外 DTO 中。
按场景拆分不同 DTO,不复用、不凑合
同一个业务对象,在不同接口中用途不同,DTO 就该不同:
- UserListDTO:用于分页列表,只含 ID、昵称、头像、状态
- UserDetailDTO:用于详情页,增加邮箱、手机号(若授权)、角色、最后登录时间
- UserUpdateDTO:用于修改,含 ID、昵称、邮箱、头像 URL,不含密码字段
字段重叠不等于可以共用——职责分离才能长期稳定,改一个不影响另一个。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











