Maven 多模块拆分:如何将 50 万行单体项目拆分为独立模块?(附拆分策略)
【摘要】 一个项目越来越臃肿,编译要20分钟,找个类要翻半天——这时候就该考虑拆分了。本文从实际项目出发,讲讲怎么用 Maven 把大单体拆成多个独立模块,包括模块划分思路、依赖关系处理、版本管理等内容。
Maven 多模块拆分:如何将 50 万行单体项目拆分为独立模块?(附拆分策略)
在开始之前,先把华为云 Maven 镜像配上,国内下载速度会快很多:
<!-- 配置华为云 Maven 镜像(推荐) -->
<!-- 修改 ~/.m2/settings.xml,添加: -->
<mirror>
<id>huaweicloud</id>
<mirrorOf>central</mirrorOf>
<url>https://repo.huaweicloud.com/repository/maven/</url>
</mirror>
或者在华为云 CodeArts Pipeline 中使用:
mvn clean package -DskipTests
推荐: 在华为云环境下使用 Maven,建议优先配置华为云镜像仓库(
https://repo.huaweicloud.com/repository/maven/)替代国外中央仓库,延迟降低 80%+,稳定性 99.99%。所有实战代码无需修改即可在华为云鲲鹏 ARM 服务器上运行。
前言:为什么要拆分多模块?
1.1 单体项目的痛点
场景一:代码臃肿不堪
一个项目 50+ 万行代码
IDEA 索引就要 5 分钟
找个类如同大海捞针
编译一次 20 分钟起步
新人看到就想跑...
场景二:团队协作困难
10 个人改同一个项目
每天都在解决代码冲突
你改了我的配置,我改了你的类
合并代码像打仗一样
场景三:复用性差
同样的工具类,3 个项目都在复制粘贴
同样的业务逻辑,每个系统都写一遍
想复用一个模块,发现耦合太严重
场景四:部署不灵活
改一个小功能,要重新部署整个系统
牵一发而动全身
不敢轻易上线
1.2 多模块的优势


第一章:模块拆分原则
2.1 核心指导思想
高内聚低耦合:
- 模块内部高度相关
- 模块之间依赖最小化
- 单向依赖,避免循环
单一职责:
- 每个模块只做一件事
- 职责边界清晰
- 易于理解和维护
稳定依赖原则:
- 不稳定模块依赖稳定模块
- 业务模块依赖基础模块
- 底层模块不能依赖上层模块
2.2 两种主流拆分方式
方式一:按功能拆分(推荐⭐⭐⭐⭐⭐)
parent/
├── common/ # 公共模块
│ ├── common-util/ # 工具类
│ ├── common-constant/ # 常量定义
│ └── common-exception/# 异常处理
├── user/ # 用户模块
│ ├── user-api/ # API 接口
│ ├── user-service/ # 业务逻辑
│ └── user-dao/ # 数据访问
├── order/ # 订单模块
│ ├── order-api/
│ ├── order-service/
│ └── order-dao/
└── web/ # Web 层
├── admin-web/ # 管理后台
└── app-web/ # C 端应用
优点:
- ✅ 业务边界清晰
- ✅ 便于团队分工
- ✅ 易于扩展和维护
方式二:按层次拆分
parent/
├── api-gateway/ # API 网关
├── service-layer/ # 服务层
│ ├── user-service/
│ ├── order-service/
│ └── product-service/
├── dao-layer/ # 持久层
│ ├── user-dao/
│ ├── order-dao/
│ └── product-dao/
└── web-layer/ # Web 层
├── controller/
└── dto/
优点:
- ✅ 层次分明
- ✅ 技术栈统一
- ✅ 便于标准化管理
第二章:实战案例 - 电商平台拆分
3.1 项目背景
原始状态:
- 单体项目,80 万行代码
- 包含用户、商品、订单、支付等功能
- 20 人开发团队
- 编译时间 25 分钟
- 部署频率每周 1 次
目标:
- 拆分成多个独立模块
- 支持独立编译和部署
- 为微服务化做准备
- 编译时间控制在 5 分钟内
3.2 最终模块结构
ecommerce-platform/ # 父项目
├── pom.xml
├── docs/ # 文档目录
├── scripts/ # 脚本目录
│
├── platform-common/ # 平台公共模块
│ ├── pom.xml
│ ├── src/
│ │ ├── main/java/com/company/common/
│ │ │ ├── util/ # 工具类
│ │ │ │ ├── DateUtil.java
│ │ │ │ ├── StringUtil.java
│ │ │ │ └── JsonUtil.java
│ │ │ ├── constant/ # 常量定义
│ │ │ │ ├── ErrorCode.java
│ │ │ │ └── SystemConstant.java
│ │ │ ├── exception/ # 异常处理
│ │ │ │ ├── BusinessException.java
│ │ │ │ └── GlobalExceptionHandler.java
│ │ │ └── response/ # 统一响应
│ │ │ ├── Result.java
│ │ │ └── PageResult.java
│
├── user-center/ # 用户中心
│ ├── pom.xml
│ ├── user-api/ # 用户 API
│ │ ├── src/main/java/
│ │ │ └── com/company/user/api/
│ │ │ ├── UserService.java # 服务接口
│ │ │ ├── dto/ # DTO 对象
│ │ │ │ ├── UserDTO.java
│ │ │ │ └── LoginRequest.java
│ │ │ └── vo/ # VO 对象
│ │ │ ├── UserVO.java
│ │ │ └── UserInfoVO.java
│ │
│ ├── user-service/ # 用户服务实现
│ │ ├── src/main/java/
│ │ │ └── com/company/user/service/
│ │ │ ├── UserServiceImpl.java
│ │ │ ├── manager/ # 业务管理器
│ │ │ │ ├── UserManager.java
│ │ │ │ └── AuthManager.java
│ │ │ └── converter/ # 对象转换
│ │ │ └── UserConverter.java
│ │
│ └── user-dao/ # 用户数据访问
│ ├── src/main/java/
│ │ └── com/company/user/dao/
│ │ ├── UserMapper.java
│ │ └── entity/ # 实体类
│ │ └── UserDO.java
│ └── src/main/resources/
│ └── mapper/UserMapper.xml
│
├── product-center/ # 商品中心
│ ├── product-api/
│ ├── product-service/
│ └── product-dao/
│
├── order-center/ # 订单中心
│ ├── order-api/
│ ├── order-service/
│ └── order-dao/
│
├── pay-center/ # 支付中心
│ ├── pay-api/
│ ├── pay-service/
│ └── pay-dao/
│
└── web-gateway/ # Web 网关
├── pom.xml
├── src/main/java/
│ └── com/company/web/
│ ├── controller/ # 控制器
│ │ ├── UserController.java
│ │ ├── OrderController.java
│ │ └── ProductController.java
│ ├── config/ # 配置类
│ │ ├── WebConfig.java
│ │ ├── SecurityConfig.java
│ │ └── SwaggerConfig.java
│ └── filter/ # 过滤器
│ ├── AuthFilter.java
│ └── LogFilter.java
└── src/main/resources/
├── application.yml
└── banner.txt
3.3 父 POM 配置
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0">
<modelVersion>4.0.0</modelVersion>
<groupId>com.company</groupId>
<artifactId>ecommerce-platform</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>pom</packaging>
<!-- 模块声明 -->
<modules>
<module>platform-common</module>
<module>user-center</module>
<module>product-center</module>
<module>order-center</module>
<module>pay-center</module>
<module>web-gateway</module>
</modules>
<!-- 统一属性管理 -->
<properties>
<java.version>17</java.version>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<!-- Spring Boot 版本 -->
<spring-boot.version>3.2.0</spring-boot.version>
<!-- 数据库相关 -->
<mysql.version>8.2.0</mysql.version>
<mybatis-plus.version>3.5.4</mybatis-plus.version>
<!-- 中间件 -->
<redis.version>3.2.0</redis.version>
<rocketmq.version>2.2.3</rocketmq.version>
<!-- 工具类 -->
<guava.version>32.1.3-jre</guava.version>
<lombok.version>1.18.30</lombok.version>
<hutool.version>5.8.23</hutool.version>
</properties>
<!-- 依赖管理(子模块可选择使用) -->
<dependencyManagement>
<dependencies>
<!-- Spring Boot Dependencies -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- 平台公共模块 -->
<dependency>
<groupId>com.company</groupId>
<artifactId>platform-common</artifactId>
<version>${project.version}</version>
</dependency>
<!-- 用户中心 -->
<dependency>
<groupId>com.company</groupId>
<artifactId>user-api</artifactId>
<version>${project.version}</version>
</dependency>
<!-- 其他内部依赖 -->
<!-- ... -->
</dependencies>
</dependencyManagement>
<!-- 构建配置 -->
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring-boot.version}</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
3.4 子模块 POM 示例
<!-- user-service/pom.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<project>
<parent>
<groupId>com.company</groupId>
<artifactId>user-center</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<artifactId>user-service</artifactId>
<packaging>jar</packaging>
<dependencies>
<!-- 依赖用户 API(定义接口) -->
<dependency>
<groupId>com.company</groupId>
<artifactId>user-api</artifactId>
</dependency>
<!-- 依赖平台公共模块 -->
<dependency>
<groupId>com.company</groupId>
<artifactId>platform-common</artifactId>
</dependency>
<!-- Spring Boot 核心 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<!-- 数据库访问 -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>${mybatis-plus.version}</version>
</dependency>
<!-- Redis 缓存 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- Lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!-- 测试依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
第三章:关键问题解决
4.1 避免循环依赖
什么是循环依赖?
A 模块依赖 B 模块
B 模块又依赖 A 模块
形成 A → B → A 的循环
危害:
❌ 无法独立编译
❌ 代码耦合严重
❌ 难以维护和测试
真实案例:
// 错误示范
// user-service 依赖 order-service
public class UserService {
@Autowired
private OrderService orderService; // ❌ 循环依赖开始
public User getUser(Long userId) {
List<Order> orders = orderService.getUserOrders(userId);
// ...
}
}
// order-service 又依赖 user-service
public class OrderService {
@Autowired
private UserService userService; // ❌ 形成循环
public List<Order> getUserOrders(Long userId) {
User user = userService.getUser(userId);
// ...
}
}
解决方案:
<!-- 方案 1: 抽取公共 API 模块 -->
user-api/
├── UserService.java # 只定义接口
├── UserDTO.java
└── OrderDTO.java # 订单的 DTO 也放这里
order-api/
├── OrderService.java
└── OrderDTO.java
user-service/
└── UserServiceImpl.java # 实现类,只依赖 user-api
order-service/
└── OrderServiceImpl.java # 只依赖 order-api 和 user-api
依赖关系:
user-service → user-api
order-service → order-api + user-api
✅ 单向依赖,无循环
4.2 版本统一管理
<!-- 父 POM 中统一定义版本 -->
<properties>
<!-- 第三方库版本 -->
<spring-boot.version>3.2.0</spring-boot.version>
<mysql.version>8.2.0</mysql.version>
<!-- 内部模块版本 -->
<project.version>1.0.0-SNAPSHOT</project.version>
</properties>
<!-- 子模块使用父 POM 定义的版本 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<!-- 不需要写版本号,自动继承 -->
</dependency>
<dependency>
<groupId>com.company</groupId>
<artifactId>platform-common</artifactId>
<!-- 自动使用${project.version} -->
</dependency>
4.3 处理 SNAPSHOT 版本
# 开发阶段使用 SNAPSHOT
<version>1.0.0-SNAPSHOT</version>
# 好处:
# - 可以随时发布新版本
# - 依赖方总能获取最新代码
# 注意事项:
# 1. CI/CD流水线要强制更新
mvn clean install -U
# 2. 生产环境使用 RELEASE 版本
<version>1.0.0</version>
# 3. 定期清理本地仓库
mvn dependency:purge-local-repository
第四章:编译与部署优化
5.1 并行编译
# 使用多线程加速编译
mvn clean install -T 4
# 根据 CPU 核心数自动调整
mvn clean install -T 1C
# 效果对比:
# 串行编译:25 分钟
# 4 线程并行:8 分钟
# 提升:68%
5.2 增量编译
# 只编译变更的模块
cd user-service
mvn clean install
# 或者使用-pl参数
mvn install -pl :user-service -am
# -am 表示同时编译依赖的模块
5.3 跳过不必要的操作
# 快速构建(跳过测试)
mvn clean package -DskipTests
# 更彻底(跳过测试和检查)
mvn clean package -Dmaven.test.skip=true \
-Dpmd.skip=true \
-Dcheckstyle.skip=true
第五章:最佳实践总结
6.1 模块划分 checklist
✅ 好的模块特征:
□ 职责单一,功能聚焦
□ 有清晰的边界
□ 可以独立编译和测试
□ 被其他模块依赖但不依赖其他模块
□ 有明确的复用价值
❌ 不好的模块特征:
□ 什么都往里塞(大杂烩)
□ 与其他模块循环依赖
□ 无法独立运行
□ 职责模糊不清
6.2 命名规范
<!-- 推荐命名方式 -->
<artifactId>xxx-api</artifactId> <!-- API 接口层 -->
<artifactId>xxx-service</artifactId> <!-- 业务逻辑层 -->
<artifactId>xxx-dao</artifactId> <!-- 数据访问层 -->
<artifactId>xxx-common</artifactId> <!-- 公共模块 -->
<artifactId>xxx-util</artifactId> <!-- 工具类 -->
<!-- 不推荐 -->
<artifactId>module1</artifactId> <!-- 无意义 -->
<artifactId>test-module</artifactId> <!-- 容易混淆 -->
6.3 依赖管理原则
依赖方向:
Web 层 → Service 层 → DAO 层
↓ ↓ ↓
Common 工具层(最底层,无依赖)
依赖规则:
✅ 上层可以依赖下层
✅ 同层可以依赖(通过 API)
❌ 下层不能依赖上层
❌ 避免跨层依赖(除非必要)
福利:一键构建脚本
#!/bin/bash
# build-all.sh - 多模块项目一键构建脚本
set -e # 遇到错误立即退出
echo "🏗️ Maven 多模块项目构建脚本"
echo "=============================="
# 参数解析
PROFILE=${1:-dev} # 默认 dev 环境
SKIP_TESTS=${2:-true}
echo "环境:$PROFILE"
echo "跳过测试:$SKIP_TESTS"
echo ""
# 1. 清理
echo "1. 清理旧构建..."
mvn clean
# 2. 安装父 POM
echo "2. 安装父 POM..."
mvn install -pl . -am -P$PROFILE
# 3. 构建公共模块
echo "3. 构建公共模块..."
mvn install -pl platform-common -am -P$PROFILE \
-DskipTests=$SKIP_TESTS
# 4. 构建各业务中心
for center in user-center product-center order-center pay-center; do
echo "构建 $center..."
mvn install -pl $center -am -P$PROFILE \
-DskipTests=$SKIP_TESTS
done
# 5. 构建 Web 网关
echo "构建 web-gateway..."
mvn package -pl web-gateway -am -P$PROFILE \
-DskipTests=$SKIP_TESTS
# 6. 统计信息
echo ""
echo "✅ 构建完成!"
echo ""
echo "📊 构建统计:"
find . -name "*.jar" -type f | wc -l | xargs echo "生成 jar 包数:"
du -sh target/ 2>/dev/null | cut -f1 | xargs echo "构建产物大小:"
echo ""
echo "🎉 恭喜!可以部署了!"
成本核算与 ROI 分析
多模块拆分的成本收益

| 项目 | 单体架构 | 多模块架构 | 提升 |
|---|---|---|---|
| 编译时间 | 25 分钟 | 8 分钟(增量 3 分钟) | 68-88% |
| 构建失败率 | 30% | 8% | 73% |
| 模块复用率 | 0% | 60%+ | - |
| 新人上手时间 | 2 周 | 3 天 | 79% |
| 部署灵活性 | 整体部署 | 按模块部署 | 质变 |
| 年度人力节省 | - | - | 约 20 万元 |
实施投入:约 5 人天(含测试),ROI 约 40 倍。
华为云实践建议
CCE 云容器引擎微服务部署
多模块项目拆分后,配合华为云 CCE 实现微服务独立部署:
# 华为云 CCE 微服务部署配置
apiVersion: apps/v1
kind: Deployment
metadata:
name: user-service
namespace: production
spec:
replicas: 3
template:
spec:
containers:
- name: user-service
image: swr.cn-north-4.myhuaweicloud.com/project/user-service:1.0.0
resources:
requests:
cpu: "500m"
memory: "512Mi"
limits:
cpu: "2000m"
memory: "2Gi"
SWR 镜像仓库多模块管理
# 推送各模块镜像到华为云 SWR
docker login -u cn-north-4@XXXXXXXX -p XXXXXX swr.cn-north-4.myhuaweicloud.com
# 推送用户服务镜像
docker tag user-service:1.0.0 swr.cn-north-4.myhuaweicloud.com/project/user-service:1.0.0
docker push swr.cn-north-4.myhuaweicloud.com/project/user-service:1.0.0
# 推送订单服务镜像
docker tag order-service:1.0.0 swr.cn-north-4.myhuaweicloud.com/project/order-service:1.0.0
docker push swr.cn-north-4.myhuaweicloud.com/project/order-service:1.0.0
总结
| 问题 | 解决方案 |
|---|---|
| 模块边界怎么划? | 按业务域划分,用户模块、订单模块等 |
| 循环依赖怎么办? | 抽取公共 API 模块单向依赖 |
| 版本怎么管? | 在父 POM 的 <properties> 统一声明 |
| 编译太慢? | 用 -T 参数并行编译,或只编译改动的模块 |
关键建议:
- 拆分前先画出模块依赖图,避免循环依赖
- 公共代码单独建模块,不要散落在业务模块里
- 多模块项目建议用
mvn install -pl xxx -am只构建需要的模块 - 结合华为云 CCE/SWR 实现微服务独立部署与镜像管理
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)