1. 概述#
- 本文主要描述 Maven 多模块项目如何创建。
- 描述什么是多模块项目以及使用该方法的好处。
2. Maven 的多模块项目#
- 一个多模块项目根据一个聚合 pom 文件构建,该文件管理一组子模块。
- 在大多数情况下,聚合 pom 文件位于项目的根目录下,并且打包方式为 pom。
- 子模块是常规的 Maven 项目,并且它们也能被单独构建。
- 通过聚合 POM 来构建项目,每个打包方式不为 pom 的项目都会被打包进最终的项目文件中。
3. 使用多模块的好处#
- 最显著的好处是我们能够减少重复和冲突。
- 假设我们有包含若干个模块的应用程序,一个前端模块和一个后端模块。
- 现在想象我们在它们之上构建项目,并且修改配置对二者都生效的配置项,使用多模块就很容易办到。
4. 父 POM#
- Maven 通过让每个 pom 文件都有父 pom 文件来支持继承。
- 除了继承,Maven 还提供了聚合的概念,一个支持聚合的父 POM 文件被称为聚合 POM,这种 POM 在它的 pom 文件中声明聚合的模块。
5. 子模块#
- 子模块,或者子项目,是继承自父 POM 文件的常规项目。
- 继承可以让子项目共享配置和依赖。
- 然而,如果我们想要一起编译和发布项目,就必须要在父 POM 文件中显式声明。
6. 构建应用程序#
现在我们创建一个程序来演示这项功能,该程序包含三个模块:
- 领域核心模块
- 提供 REST 接口的 web 服务模块
- 包含用户可视化资源的 webapp
6.1. 生成父 POM 文件#
- 首先,需要创建一个父项目:
1
| mvn archetype:generate -DgroupId=com.baeldung -DartifactId=parent-project
|
- 父项目一旦被创建,我们需要打开 pom.xml 文件夹,并且添加打包方式为 pom:
1
| <packaging>pom</packaging>
|
- 通过设置 pom 类型的打包方式,我们声明该项目将会是一个父项目,或者是一个聚合项目,它不会生成打包内容。
- 当我们的聚合完成后,我们可以生成我们的子模块。
6.2. 创建子模块#
- 在创建子模块之前,需要确认我们在父项目的文件夹中,然后运行如下生成指令:
1
2
3
4
| cd parent-project
mvn archetype:generate -DgroupId=com.baeldung -DartifactId=core
mvn archetype:generate -DgroupId=com.baeldung -DartifactId=service
mvn archetype:generate -DgroupId=com.baeldung -DartifactId=webapp
|
- 在父项目的 pom 文件中,我们需要在 modules 部分添加所有的子模块:
1
2
3
4
5
| <modules>
<module>core</module>
<module>service</module>
<module>webapp</module>
</modules>
|
- 在每个子模块中,我们需要在
<parent> 元素内部添加父模块:
1
2
3
4
5
| <parent>
<artifactId>parent-project</artifactId>
<groupId>com.baeldung</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
|
- 注意,每个子模块只能由有一个父模块
6.3. 构建项目#
- 现在,我们可以一次构建所有的三个项目:
- 该命令会构建所有的模块,我们可以看到命令的输出如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
| [INFO] Scanning for projects...
[INFO]
------------------------------------------------------------------------
[INFO] Reactor Build Order:
[INFO] parent-project
[pom]
[INFO] core
[jar]
[INFO] service
[jar]
[INFO] webapp
[war]
[INFO] Reactor Summary for parent-project 1.0-SNAPSHOT:
[INFO] parent-project ..................................... SUCCESS [ 0.272 s]
[INFO] core ............................................... SUCCESS [ 2.043 s]
[INFO] service ............................................ SUCCESS [ 0.627 s]
[INFO] webapp ............................................. SUCCESS [ 0.572 s]
[INFO]
------------------------------------------------------------------------[INFO]
BUILD SUCCESS
[INFO]
------------------------------------------------------------------------
|
- 此外,Maven Reactor也会分析我们的项目并且按照指定的顺序来构建项目,所以如果我们的 webapp 模块依赖 service 模块,Maven 将会首先构建 service,然而再构建 webapp。
6.4. 在父项目中启用依赖管理#
- 依赖管理是一种在多模块项目中集中依赖信息的机制。
- 当我们有一些项目或模块依赖一个公共的父项目时,我们可以把所有需要的依赖信息都放在公共的 pom.xml 文件中。
1
2
3
4
5
6
7
8
9
| <dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.3.16</version>
</dependency> //...
</dependencies>
</dependencyManagement>
|
- 通过在父项目中声明 spring-core 的版本号,所有依赖它的项目都只需要声明 groupId 和 artifactId 即可,version 将会被继承:
1
2
3
4
5
6
7
| <dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
</dependency>
//...
</dependencies>
|
- 此外,我们还可以在父项目中剔除依赖,所以指定的库不会被子项目继承:
1
2
3
4
5
6
| <exclusions>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</exclusion>
</exclusions>
|
- 最后,如果一个子模块需要使用不同于父项目的版本号,可以自行指定版本号来覆盖父项目中的配置:
1
2
3
4
5
| <dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.3.30.RELEASE</version>
</dependency>
|
6.5. 更新子模块并构建项目#
- 我们可以修改每一个子模块的打包方式。