在微服务架构中,清晰的目录结构(Project Structure)是保障可维护性、可扩展性和团队协作效率的基础。如何设计既能体现 领域驱动设计(DDD)思想,又符合 Spring Boot 技术栈最佳实践 的目录结构是成为架构师的必修知识。
下面我将从 单个微服务内部结构 层面,系统阐述目录划分原则、各层职责及实战示例。
一、单个微服务内部目录结构(推荐:六边形架构 + DDD 分层)
✅ 核心思想:关注点分离(Separation of Concerns) + 领域模型优先
标准目录结构(Maven 多 Module 模式)
user-service/ # 服务根目录
├── pom.xml
├── user-api/ # 1. 对外暴露的接口契约
├── user-application/ # 2. 应用层(Spring Boot 启动入口)
├── user-domain/ # 3. 领域层(核心业务逻辑)
├── user-infrastructure/ # 4. 基础设施层(技术实现)
└── user-common/ # 5. 公共模块(可选)
1. user-api:接口契约层(Interface Contract)
📁 目录结构
user-api/
├── src/main/java
│ └── com/company/user/api
│ ├── dto/ # 数据传输对象(DTO)
│ ├── feign/ # Feign 客户端接口(供其他服务调用)
│ └── exception/ # 公共异常定义
└── pom.xml
🎯 定位与作用
- 定义服务对外暴露的 API 契约
- 其他服务通过依赖此模块调用本服务
- DTO 与领域模型解耦(避免暴露内部结构)
💡 关键实践
- DTO 使用
@Data(Lombok),不包含业务逻辑 - Feign 接口使用
@FeignClient,方法签名与 Controller 一致 - 禁止依赖
user-domain(避免循环依赖)
2. user-application:应用层(Application Layer)
📁 目录结构
user-application/
├── src/main/java
│ └── com/company/user/application
│ ├── UserApplication.java # Spring Boot 启动类
│ ├── config/ # Spring 配置类
│ ├── controller/ # REST API 控制器
│ └── assembler/ # DTO 与领域对象转换器
└── src/main/resources
├── application.yml # 应用配置
└── bootstrap.yml # 服务注册/配置中心配置
🎯 定位与作用
- 协调领域层完成用例(Use Case)
- 处理 HTTP 请求/响应
- 事务边界控制(
@Transactional)
💡 关键实践
- Controller 只做参数校验和 DTO 转换
- 业务逻辑委托给
user-domain的 Application Service - 依赖
user-api和user-domain
3. user-domain:领域层(Domain Layer)【核心!】
📁 目录结构
user-domain/
├── src/main/java
│ └── com/company/user/domain
│ ├── model/ # 领域模型(聚合根、实体、值对象)
│ ├── repository/ # 领域仓库接口(抽象)
│ ├── service/ # 领域服务(核心业务逻辑)
│ └── event/ # 领域事件
└── pom.xml
🎯 定位与作用
- 封装核心业务规则和逻辑
- 与技术细节完全解耦(无 Spring、无数据库依赖)
- 高内聚、可测试、可复用
💡 关键实践
- 聚合根(Aggregate Root) 是操作入口(如
User) - 实体(Entity) 有唯一标识,值对象(Value Object) 无标识
- Repository 只定义接口,实现在
user-infrastructure - 禁止依赖其他层(纯 Java 代码)
4. user-infrastructure:基础设施层(Infrastructure Layer)
📁 目录结构
user-infrastructure/
├── src/main/java
│ └── com/company/user/infrastructure
│ ├── config/ # MyBatis/DataSource 配置
│ ├── persistence/ # 数据库持久化实现
│ │ ├── mapper/ # MyBatis Mapper
│ │ ├── po/ # 持久化对象(PO)
│ │ └── repository/impl/ # Repository 接口实现
│ ├── mq/ # 消息队列实现
│ └── external/ # 第三方服务调用(如短信、支付)
└── pom.xml
🎯 定位与作用
- 实现技术细节(数据库、MQ、HTTP 客户端)
- 依赖外部框架(MyBatis, RocketMQ, Feign)
- 为领域层提供技术支撑
💡 关键实践
- PO 与 DTO 严格分离
- Repository 实现 只处理数据映射,不包含业务逻辑
- 依赖
user-domain和user-api
5. user-common:公共模块(可选)
📁 目录结构
user-common/
├── src/main/java
│ └── com/company/common
│ ├── exception/ # 全局异常
│ ├── util/ # 工具类
│ └── constant/ # 全局常量
└── pom.xml
🎯 定位与作用
- 跨服务共享的通用代码
- 避免重复造轮子
⚠️ 注意
- 谨慎使用!过度共享会导致隐式耦合
- 优先考虑 复制代码(Copy-Paste)而非共享
二、关键设计原则(高级开发者必看)
1. 依赖方向:向内依赖
user-application → user-domain → user-infrastructure
↓ ↑
user-api ←──────────┘
- 高层模块依赖低层模块,低层模块不依赖高层
- 领域层是核心,不依赖任何技术框架
2. 包命名规范
- 避免按技术分层命名(如
com.xxx.controller) - 按业务能力命名(如
com.xxx.user)
3. 测试目录对应
src/test/java
└── com/company/user
├── application/ # 应用层测试(集成测试)
├── domain/ # 领域层测试(单元测试)
└── infrastructure/ # 基础设施测试(集成测试)
三、避坑指南
| 坑 | 正确做法 |
|---|---|
| 贫血模型 | 领域对象包含行为(方法),不只是 getter/setter |
| 事务蔓延 | 事务只在 Application 层开启,领域层无 @Transactional |
| DTO 污染 | DTO 不包含业务逻辑,不继承领域对象 |
| 循环依赖 | 通过事件驱动解耦(如 Spring ApplicationEvent) |
四、总结:目录结构设计 Checklist
| 层级 | 是否做到? |
|---|---|
| API 层 | 只定义 DTO 和 Feign 接口,无业务逻辑 |
| 应用层 | 只协调用例,不包含核心业务规则 |
| 领域层 | 纯 Java 代码,无 Spring/DB 依赖 |
| 基础设施层 | 实现技术细节,不包含业务逻辑 |
| 依赖方向 | 领域层 → 基础设施层,反向禁止 |
| 测试覆盖 | 领域层 100% 单元测试,应用层集成测试 |
💡 终极目标:
当技术栈变更(如 MyBatis → JPA)时,只需修改infrastructure层,领域逻辑零改动!

554

被折叠的 条评论
为什么被折叠?



