一、核心概念
Maven多模块项目有一个父项目(聚合项目) 和多个子模块 。父项目本身不包含业务代码,它通过<modules>聚合子模块,并通过<dependencyManagement>统一管理依赖版本。
Maven聚合项目(多模块)的模块化,本质上是为了应对软件复杂度而诞生的"分而治之"的思想。
关键配置:
- 父POM的packaging :必须为
pom。 <modules>:声明所有子模块。<dependencyManagement>:定义依赖版本(声明但不引入),子模块需显式引用所需依赖,无需指定版本。<pluginManagement>:统一管理插件配置。
二、为什么需要模块化?
想象一下你正在开发一个大型电商系统,如果不做模块化,你会得到一个单模块项目:
e-commerce/
├── src/ (所有代码混在一起)
│ ├── controller/ (用户、订单、商品...)
│ ├── service/
│ ├── dao/
│ └── utils/
└── pom.xml (一个超级大的pom文件)
这就像把所有家当都塞进一个房间,时间久了就会变成这样;
单模块项目的痛点:
-
编译慢如蜗牛:改一行代码,整个项目都要重新编译、测试、打包
-
代码纠缠不清:业务逻辑、工具类、配置全部混杂,没人说得清依赖关系
-
团队协作困难:多人修改同一模块,Git冲突频繁,代码审查痛苦
-
复用基本靠复制:想在另一个项目用这个系统的工具类?只能复制粘贴
-
构建时间越来越长:哪怕改一个前端资源,后端也要全部重跑
三、模块化后长什么样?
模块化后的电商系统是这样的:
parent-project/ (聚合父项目)
├── pom.xml (packaging=pom,统一管理版本)
├── e-commerce-common/ (公共工具模块)
│ └── pom.xml
├── e-commerce-user/ (用户模块)
│ └── pom.xml
├── e-commerce-order/ (订单模块)
│ └── pom.xml (依赖common)
├── e-commerce-product/ (商品模块)
│ └── pom.xml (依赖common)
└── e-commerce-web/ (Web入口模块)
└── pom.xml (依赖user、order、product)
四、模块化实际解决了什么?
1. 分治治理 - 降低复杂度
<!-- 每个模块只关心自己的pom.xml -->
<!-- order模块的pom.xml只需要知道自己依赖谁 -->
<dependencies>
<dependency>
<groupId>com.e-commerce</groupId>
<artifactId>e-commerce-common</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
实际效果:新人接手项目,只看order模块就能理解订单相关代码,不需要了解整个系统。
2. 增量构建 - 大幅提升效率
修改common模块时,Maven只会重新构建:
-
common模块本身
-
依赖common的模块(user、order、product)
-
间接依赖的web模块
实际效果:5分钟的全量构建变成30秒的增量构建,开发效率提升立竿见影。
3. 统一版本管理 - 告别依赖冲突
<!-- 父pom统一管理所有依赖版本 -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.7.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
实际效果:所有子模块使用同一版本,彻底避免"ClassNotFoundException"或方法不存在的问题。
4. 独立演进和部署
-
订单模块可以单独升级、单独发布
-
不同团队可以负责不同模块,互不干扰
-
公共模块可以轻松复用给其他项目
5. 清晰的边界和职责
每个模块都有明确的边界:
-
common:谁都能用,但谁都不能乱改 -
user:只处理用户相关逻辑 -
order:依赖用户模块,但不能直接改用户数据
五、构建多模块项目
1、创建父项目


父工程作为子模块的容器,且不涉及代码,因此不需要src目录,直接删除

2、创建子模块

3、构建完成,项目结构

4、父项目引入子模块

5、子模块继承父项目

6、订单模块依赖公共工具模块

五、问题归集
1.循环依赖:严禁模块间出现循环依赖(如A依赖B,B又依赖A)。Maven会报错,这同时也是糟糕设计的信号。
2.依赖作用域(Scope):合理使用compile、provided、test等作用域,避免不必要的依赖传递。例如,Servlet API在web模块中应设为provided。
3.版本管理:强烈推荐在父POM的<dependencyManagement>中统一管理所有依赖的版本,这是保持一致性的关键。
4.聚合与继承:Maven的聚合(<modules>)和继承(<parent>)通常一起使用,但它们是两个不同的概念。一个项目可以聚合但不继承其他模块,反之亦然。
五、总结
父项目 Maven 只是负责构建所有子模块各自的 jar 包,实际发布是单独发布子模块 jar 包。
-
Maven聚合(父项目)是一个"构建时的概念":它像一个总指挥,帮你一键按顺序构建好所有模块,最终生成多个独立的jar/war包。
-
模块化部署是一个"运行时的概念":这些独立生成的jar/war包,可以被单独部署、升级和发布。
-
"整体构建"是为了方便和保证一致性,"单独发布"则是为了灵活性和独立演进。 两者在Maven多模块项目中相辅相成,完美地解决了大型项目的管理和部署问题。
-
