网易首页 > 网易号 > 正文 申请入驻

解决DTO泛滥的问题

0
分享至

DTO(或 VO)的过度使用,确实会在中大型项目中带来“类爆炸”问题:一个用户实体,可能对应 UserCreateDTO 、UserUpdateDTO 、UserLoginDTO 、UserResponseVO ……不仅数量多,而且彼此相似,维护成本很高。

要解决DTO 泛滥,不能只靠包组织,需要从设计理念代码结构两方面一起优化。

一、先治本:减少不必要的DTO1. 不是每个Entity都需要单独的DTO

很多项目不敢直接将 Entity 暴露给 Controller ,但如果你能保证以下几点,完全可以复用:

  • 实体中没有敏感字段(如密码、加密盐)。
  • 实体字段命名与前端预期一致(或通过 @JsonProperty 调整)。
  • 不需要对字段进行额外格式化(如日期转换)。
  • 序列化行为可控(如忽略 @Transient 或懒加 #Java #Java EE载属性)。

实践:对内部管理系统、简单的查询接口,直接返回 Entity 或 List ,能省则省。只在需要裁剪、聚合、转换时才创建 DTO。

2. 多个场景共用同一个DTO

  • 输入输出共用:一个 UserDto 既作为 @RequestBody ,又作为返回值。通过 @JsonView (Spring)或校验分组( @Validated )区分必填字段。
  • 创建和更新共用:唯一区别是 id 字段;更新时id由路径传入,DTO中可以没有id,也可以复用但标记为可选。
  • 详情和列表共用:如果列表只比详情少几个字段,可以用同一个DTO,只是部分字段为 null ;或者用继承: UserBasicDTO 和 UserDetailDTO extends UserBasicDTO 。
3. 使用 record (Java 14+)替代传统DTO

public record UserResponse(Long id, String username, String email) {}

一行代码定义不可变 DTO,极大减少样板代码,从根源上降低“写 DTO 的抵触感”。

4. 拥抱 GraphQL 或类似技术

不再需要为每个前端视图设计专用的 DTO。前端直接声明所需字段,服务端返回准确的 JSON 结构。虽然技术栈变化较大,但能彻底消灭“响应 VO 泛滥”。

二、再治标:合理的包组织,让泛滥更可控

即使保留多个 DTO,清晰的组织也能大幅降低认知负担。

❌ 反模式:全局大杂烩

com.example.dto├── UserCreateDTO.java├── UserUpdateDTO.java├── UserLoginDTO.java├── UserResponseVO.java├── OrderCreateDTO.java

所有 DTO 堆在一起,很快就无法维护。

✅ 推荐模式:按业务模块 + 按角色分层方式一:按模块聚合,内部再分 request / response

com.example.user├── controller├── service├── repository└── dto├── request│   ├── UserCreateRequest.java│   ├── UserUpdateRequest.java│   └── UserQueryRequest.java└── response├── UserDetailResponse.java└── UserListResponse.java

优点:同一个业务的所有 DTO 内聚在一起,request/response 一目了然。

方式二:直接按使用场景命名,放在 model 包下

com.example.user.model├── UserRequest.java     // 包含所有可能的请求字段(通过校验组区分)├── UserResponse.java    // 全量返回└── UserBriefResponse.java // 精简版

对于小型项目足够,无需再分 request/response 子包。

方式三:将DTO与API定义放在一起(契约优先)

com.example.api.user├── UserApi.java         // Feign 或 Controller 接口├── CreateUserCommand.java├── UpdateUserCommand.java├── UserView.java└── UserSummaryView.java

特别适合微服务之间或前后端严格基于 Swagger/OpenAPI 的开发模式。

核心原则

  • 内聚性:和谁一起变,就和谁放在一起。用户相关的DTO永远放在 user 包内,不要跨模块共用(除非是全局公共DTO)。
  • 可见性:包名后缀直接表达意图 —— request / response / command / view / dto 均可,但全项目统一。
  • 限制层级:最多两层(模块 + 角色),不要出现 dto.request.create.v1 这种过度嵌套。
三、配套工具与规范
  1. MapStruct 或 BeanUtils:即使DTO多,转换代码也要极简。
  2. ArchUnit 写规则:禁止从 Controller 直接返回 Entity 类型(除非在指定白名单内)。
  3. 定期重构:如果发现两个DTO字段完全一致,果断合并;如果发现DTO与Entity字段完全一致且无额外逻辑,考虑删除DTO直接暴露Entity。
四、总结:最佳实践清单

| 问题 | 解决策略 | 包组织示例 | | ---

| 输入、输出 DTO 几乎一样 | 合并为一个 DTO,用 @JsonView 区分 | user.dto.UserDto | | 创建和更新只有 id 不同 | 统一用 UserUpsertRequest,id 放在路径中 | user.dto.request.UserUpsertRequest | | 列表和详情返回不同字段 | 继承:UserBaseView +

| 全局公用的分页参数、结果 | 抽象为 PageRequest 和 PageResponse | common.dto.PageRequest, common.dto.PageResponse | | 多个模块共用同一个实体(如 Address) | 放在公共模块 common.model.Address,不作为 DTO | 直接复用 POJO |

核心思想:不要为了分层而分层。当你能用 Entity 、能复用、能用 record 、能用继承时,就不要新建一个独立的 DTO 类。当确实需要多个 DTO 时,用业务模块 + 请求/响应子包的方式组织,避免全局混乱。

特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。

Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.

相关推荐
热点推荐
最弱的部门,怎么变成了最有权的

最弱的部门,怎么变成了最有权的

晚风也遗憾
2026-05-13 07:22:41
白鹿黑历史被大起底,对前辈无礼学历造假,发布辱华辱女争议视频

白鹿黑历史被大起底,对前辈无礼学历造假,发布辱华辱女争议视频

花哥扒娱乐
2026-05-13 19:10:45
央视主持大调整:三人告别,杨帆遇冷,撒贝宁朱迅情况最意外

央视主持大调整:三人告别,杨帆遇冷,撒贝宁朱迅情况最意外

吕彏极限手工
2026-05-12 19:04:49
报应来得太快!印尼对华镍矿挥刀制裁,仅 20 多天就自食苦果认怂

报应来得太快!印尼对华镍矿挥刀制裁,仅 20 多天就自食苦果认怂

黑鹰观军事
2026-05-13 15:32:20
全面升级!湖南“湘十条”楼市新政落地

全面升级!湖南“湘十条”楼市新政落地

中指研究院
2026-05-13 20:37:27
45岁小沈阳被曝十天进两次急诊,背后原因太心酸,给中年人提个醒

45岁小沈阳被曝十天进两次急诊,背后原因太心酸,给中年人提个醒

青梅侃史啊
2026-05-14 07:21:59
库里盼至少征战20年!大概率与勇士签1+1合同 格林愿降薪助队引援

库里盼至少征战20年!大概率与勇士签1+1合同 格林愿降薪助队引援

罗说NBA
2026-05-14 06:48:29
花20亿养上百位情人,睡十人大床,风流一生临终却落个凄惨结局?

花20亿养上百位情人,睡十人大床,风流一生临终却落个凄惨结局?

历史人文2
2026-04-09 19:16:31
钱再多有什么用?2个女儿惨死3个儿子反目,资产1250亿也无人送终

钱再多有什么用?2个女儿惨死3个儿子反目,资产1250亿也无人送终

北纬的咖啡豆
2026-04-08 17:09:30
北京时间5月13日,湖人核心东契奇突然在社交平台官宣重磅消息!

北京时间5月13日,湖人核心东契奇突然在社交平台官宣重磅消息!

止境
2026-05-14 00:41:14
给《低智商犯罪》演技最好的10位演员排个名:王传君第3,王骁第2

给《低智商犯罪》演技最好的10位演员排个名:王传君第3,王骁第2

八斗小先生
2026-05-07 16:56:09
新生儿腰斩、房价下跌?别怪政策了,这才是中国经济的残酷真相!

新生儿腰斩、房价下跌?别怪政策了,这才是中国经济的残酷真相!

冷夜说
2026-05-11 20:31:08
老詹又一不满曝光!里程碑之夜未获比赛用球:付出被视作理所当然

老詹又一不满曝光!里程碑之夜未获比赛用球:付出被视作理所当然

罗说NBA
2026-05-14 06:52:22
约0.01飞米!中国科学家重要发现,将改写教科书

约0.01飞米!中国科学家重要发现,将改写教科书

上观新闻
2026-05-14 06:48:04
男子自驾到浙江,出收费站发现手机坏了无法付通行费,浙江收费员当场垫付334元;想留下驾驶证作凭证被拒:安心修好手机,不用着急还款

男子自驾到浙江,出收费站发现手机坏了无法付通行费,浙江收费员当场垫付334元;想留下驾驶证作凭证被拒:安心修好手机,不用着急还款

台州交通广播
2026-05-13 16:32:28
伊朗万万没想到!刚用导弹炸完阿联酋,阵风遮天蔽日飞抵阿联酋

伊朗万万没想到!刚用导弹炸完阿联酋,阵风遮天蔽日飞抵阿联酋

爱吃醋的猫咪
2026-05-13 21:21:29
87亿打水漂!当初抢的时候多嚣张,现在就多狼狈:荷兰大臣哭晕

87亿打水漂!当初抢的时候多嚣张,现在就多狼狈:荷兰大臣哭晕

观史搜寻着
2026-05-13 12:50:11
特朗普抵京!WTO重磅数据曝光!美日德加起来都快不够打!对特朗普意味着什么 ?

特朗普抵京!WTO重磅数据曝光!美日德加起来都快不够打!对特朗普意味着什么 ?

华山穹剑
2026-05-13 21:14:12
国际足联终于慌了!紧急宣布新方案,世界杯版权将迎来重大转机

国际足联终于慌了!紧急宣布新方案,世界杯版权将迎来重大转机

甜到你心坎
2026-05-13 10:47:07
特朗普要求中国对美经贸团队访问提供便利,外交部回应

特朗普要求中国对美经贸团队访问提供便利,外交部回应

澎湃新闻
2026-05-13 15:22:26
2026-05-14 07:39:00
呼呼历史论
呼呼历史论
分享有趣的历史
572文章数 17009关注度
往期回顾 全部

科技要闻

阿里年营收首破万亿,AI终于不再是画大饼

头条要闻

中东战火烧痛印度 莫迪六天访五国要外交“救国”

头条要闻

中东战火烧痛印度 莫迪六天访五国要外交“救国”

体育要闻

14年半,74万,何冰娇没选那条更安稳的路

娱乐要闻

白鹿掉20万粉,网友为李晨鸣不平

财经要闻

美国总统特朗普抵达北京

汽车要闻

C级纯电轿跑 吉利银河"TT"申报图来了

态度原创

旅游
艺术
家居
游戏
教育

旅游要闻

泰国拟缩短93国游客免签停留期限,从60天减少至30天

艺术要闻

这才是真正的“史上最强毕业证”,书法堪比字帖!

家居要闻

内在自叙,无域有方

三角洲行动那些玄学设定,很多玩家可能都经历过这些事情

教育要闻

家长就读,孩子免费修大学学分的社区大学?

无障碍浏览 进入关怀版