本文目录导读:

Maven聚合父工程(通常称为pom打包方式的父项目)是管理多模块项目的核心方式,它主要解决两个问题:批量构建(聚合)和统一依赖管理(继承)。
以下是关于如何创建和管理 Maven 聚合父工程与子模块的详细指南。
核心概念
- 聚合(Aggregation):
- 父工程的
pom.xml中通过<modules>标签声明子模块。 - 作用:当你在父工程目录执行
mvn clean install时,Maven 会自动按照依赖关系顺序构建所有子模块。
- 父工程的
- 继承(Inheritance):
- 父工程的
pom.xml中定义公共配置(如依赖版本、插件、仓库等)。 - 子模块的
pom.xml通过<parent>标签声明继承自哪个父工程。 - 作用:消除重复配置,统一项目规范。
- 父工程的
目录结构示例
假设项目名为 my-project,包含三个子模块:common、service、web。
my-project/ # 根目录(通常就是父工程)
├── pom.xml # 父工程的 POM,packaging 为 pom
├── my-project-common/ # 子模块1
│ └── pom.xml
├── my-project-service/ # 子模块2
│ └── pom.xml
└── my-project-web/ # 子模块3
└── pom.xml
父工程 pom.xml 配置详解
父工程的 packaging 必须为 pom,这是聚合和管理子模块的前提。
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<!-- 父工程坐标 -->
<groupId>com.example</groupId>
<artifactId>my-project</artifactId>
<version>1.0.0-SNAPSHOT</version>
<!-- 关键点:打包方式必须是 pom -->
<packaging>pom</packaging>
<name>My Project Parent</name>
<description>父工程,负责管理子模块和统一依赖</description>
<!-- 1. 声明子模块(聚合) -->
<modules>
<module>my-project-common</module>
<module>my-project-service</module>
<module>my-project-web</module>
<!-- 注意:module 标签里放的是子模块的目录名(相对路径) -->
</modules>
<!-- 2. 统一属性管理 -->
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<!-- 统一管理第三方依赖版本 -->
<spring.boot.version>3.2.0</spring.boot.version>
<lombok.version>1.18.30</lombok.version>
<mysql.connector.version>8.0.33</mysql.connector.version>
</properties>
<!-- 3. 依赖管理(关键:<dependencyManagement>) -->
<!-- 这里只声明版本,不实际引入依赖 -->
<dependencyManagement>
<dependencies>
<!-- Spring Boot BOM(物料清单):引入后可以不用写版本号 -->
<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>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.connector.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
<!-- 4. 所有子模块都会继承的公共依赖(较少使用,一般放日志、lombok等) -->
<dependencies>
<!-- 所有子模块都需要 SLF4J -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>2.0.9</version>
</dependency>
</dependencies>
<!-- 5. 统一插件管理 -->
<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>${maven.compiler.source}</source>
<target>${maven.compiler.target}</target>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
子模块 pom.xml 配置详解
以 my-project-service 为例:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<!-- 1. 声明父工程(继承) -->
<parent>
<groupId>com.example</groupId>
<artifactId>my-project</artifactId>
<version>1.0.0-SNAPSHOT</version>
<!-- 相对路径:指向父工程的 pom.xml 文件 -->
<relativePath>../pom.xml</relativePath>
</parent>
<!-- 2. 子模块自己的坐标 -->
<!-- 注意:通常省略 groupId 和 version,它们会从父工程继承 -->
<artifactId>my-project-service</artifactId>
<!-- packaging 默认为 jar,如果是 web 模块可以用 war -->
<packaging>jar</packaging>
<name>My Project Service</name>
<description>业务逻辑层模块</description>
<!-- 3. 子模块自己的依赖 -->
<dependencies>
<!-- 依赖同一项目的其他子模块 -->
<dependency>
<groupId>com.example</groupId>
<artifactId>my-project-common</artifactId>
<!-- 注意:这里不需要写 version,因为父工程已管理 -->
</dependency>
<!-- 使用父工程管理的依赖,只需写 groupId 和 artifactId -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<!-- 版本号由父工程的 spring-boot-dependencies 管理 -->
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<!-- 版本由父工程的 <dependencyManagement> 管理 -->
</dependency>
</dependencies>
</project>
dependencyManagement 与 dependencies 的区别
| 特性 | <dependencies> (在父工程中) |
<dependencyManagement> (在父工程中) |
|---|---|---|
| 作用 | 所有继承的子模块强制引入该依赖 | 声明依赖的版本号,子模块按需引入 |
| 是否被子模块继承 | 是,子模块自动拥有该依赖 | 否,子模块需要显式声明 dependency |
| 典型场景 | 公共日志、Lombok、测试框架等 | Spring Boot 版本、Jackson 版本等 |
| 子模块声明时 | 无需再次声明 | 必须声明,但可以省略 version |
建议:父工程中尽量使用 <dependencyManagement> 管理版本,避免在父工程中直接放过多 <dependencies>,防止子模块被迫引入不需要的库。
常见问题与最佳实践
<relativePath> 要写吗?
- 推荐写:
<relativePath>../pom.xml</relativePath>可以提高构建的确定性。 - 可选但建议:如果不写,Maven 会先尝试从本地仓库、远程仓库查找父 POM,如果你本地的父 POM 还没有安装到仓库,构建就会失败。
子模块可以不被父工程包含吗?
- 可以,父工程只是通过
<modules>管理你需要一起构建的模块,其他项目可以通过坐标直接引用你的子模块。
版本号冲突如何处理?
- 原则:在父工程的
<dependencyManagement>中统一定义所有关键依赖的版本,子模块中尽量避免写版本号。 - 如果有必要在子模块中覆盖版本,可以在子模块的
<dependency>中明确指定version。
模块间依赖顺序
service依赖common,Maven 构建时会自动先构建common,再构建service,你不需要担心顺序。
父工程本身不包含业务代码
- 父工程的
src目录通常可以删除,它只负责管理配置。packaging为pom的项目不需要src/main/java。
构建命令
-
构建整个项目(在父工程目录下执行):
mvn clean install
-
只构建某个子模块及其依赖(在父工程目录下执行):
mvn clean install -pl my-project-service -am
-pl:指定模块-am:also make,表示同时构建该模块依赖的其他模块
-
跳过测试构建:
mvn clean install -DskipTests
通过合理的父工程设计,你可以实现:
- 一键全量构建。
- 零版本号冲突。
- 统一的开发规范(编译器版本、编码格式)。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播