You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

多模块Maven项目中DTO类与MapStruct@Mapper的放置位置问询

模块职责导向的DTO与Mapper放置方案

先明确各模块的核心职责边界:

  • xxx-api/yyy-api模块:仅负责对接外部服务,包含OpenAPI生成的模型、客户端调用逻辑,本质是外部服务的"代理层",只处理与外部服务的交互逻辑。
  • backend模块:承载业务逻辑与对外REST接口,负责聚合外部服务数据、执行业务规则,最终向前端/下游返回标准化响应。

基于职责划分,给出两种场景下的最优方案:

场景1:简化后的DTO仅为backend的REST接口服务

如果你的DTO只是为了backend控制器返回使用,优先放在backend模块,理由如下:

  • 符合单一职责:xxx-api/yyy-api只需维护与外部服务一致的模型,不用关心backend如何对外暴露数据,避免模块职责膨胀。
  • 降低耦合:外部服务API模型变更时,只需调整xxx-api/yyy-api的生成代码,以及backend内对应的Mapper和DTO,不会牵连其他模块。
  • 维护直观:REST接口的DTO属于对外契约,放在负责对外接口的backend模块,其他开发者能快速找到接口返回的模型定义。

此时的结构示例:

root
├── backend
│   └── src/main/java
│       └── com/yourcompany/backend
│           ├── dto          # 简化后的DTO,供REST控制器返回
│           ├── mapper       # MapStruct的@Mapper,处理外部模型→内部DTO的转换
│           └── controller   # REST端点
└── gateway
    ├── xxx-api
    │   └── src/main/java/com/yourcompany/gateway/xxxapi
    │       └── model        # OpenAPI生成的外部服务模型
    └── yyy-api
        └── src/main/java/com/yourcompany/gateway/yyyapi
            └── model        # OpenAPI生成的外部服务模型

注意:需在backend模块的pom中引入xxx-api/yyy-api依赖,确保能访问外部服务的模型类。

场景2:简化后的DTO需要多模块复用

如果除backend外,还有其他模块(比如未来新增的frontend-client或其他服务)需要使用这些DTO,建议新增独立的shared-dto模块:

  • shared-dto模块依赖xxx-api/yyy-api,统一维护DTO和转换Mapper
  • backend及其他需要的模块依赖shared-dto,直接复用转换后的DTO

这种方案避免了重复定义DTO,同时保持各模块职责清晰。

不建议放在xxx-api/yyy-api模块的原因

将DTO和Mapper放在外部服务的api模块会带来两个核心问题:

  1. 职责混淆:xxx-api原本只负责对接外部服务,现在额外承担为backend提供DTO的职责,违反单一职责原则。
  2. 耦合风险:如果backend对DTO的需求变更(比如新增字段、调整结构),需要修改xxx-api模块,但该模块本应只跟随外部服务的API变化。

总结

  • 若DTO仅服务于backend的REST接口:放在backend模块,Mapper一同置于此处,依赖xxx-api/yyy-api完成转换。
  • 若DTO需要多模块复用:新增shared-dto模块统一维护,让依赖该DTO的模块引用此模块。

核心原则就是让每个模块只做它最核心的事情,避免跨职责的代码堆积,不用过度复杂化。

内容的提问来源于stack exchange,提问作者Marcin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 19:17:07