9. 父子模块
在 Maven 中,父子模块(或称多模块项目)是一种用来管理和构建包含多个子项目的复杂项目结构。父子模块配置允许子项目通过继承父项目的一些配置来减少重复配置,统一进行管理,提高复用性和统一性,从而提高开发效率。通过父子模块配置,Maven 提供了良好的模块化管理,使得子项目之间的依赖关系和配置更加清晰,并简化了多模块项目的构建过程。
9.1 基本结构
一个 Maven 父子模块项目通常包含一个顶层父项目,以及多个作为其子项目的模块。典型的目录结构如下:
project/
│
├── pom.xml # 顶层父项目的 POM 文件
│
├── module-a/ # 子模块 A
│ └── pom.xml
│
├── module-b/ # 子模块 B
│ └── pom.xml
│
└── module-c/ # 子模块 C
└── pom.xml
- 父项目 POM 文件:通常用于定义项目的公共配置,如依赖、插件、属性等。父项目不生成具体的构件,而是用于聚合和管理子模块。
- 子模块 POM 文件:每个子模块都有自己的 pom.xml 文件,但会通过
<parent>
标签指向父项目的配置。
在顶层父项目的 pom.xml 文件中,一般会包含以下几个关键配置:
<project xmlns="http://maven.apache.org/POM/4.0.0" ...>
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>project</artifactId>
<version>1.0.0</version>
<packaging>pom</packaging> <!-- 父项目通常是 POM 类型 -->
<modules>
<module>module-a</module>
<module>module-b</module>
<module>module-c</module>
</modules>
<dependencyManagement>
<!-- 定义子模块中通用的依赖版本 -->
</dependencyManagement>
<build>
<pluginManagement>
<!-- 定义子模块中通用的插件版本 -->
</pluginManagement>
</build>
</project>
<packaging>pom</packaging>
:父项目的 packaging 类型通常设为 pom,表示它不会生成任何构件,只是用于聚合。<modules>
:列出了父项目所包含的子模块,这些模块相对于父项目的路径。<dependencyManagement>
:统一定义所有子模块的依赖版本,避免在每个子模块中重复定义依赖版本号。<pluginManagement>
:用于管理插件的版本,子模块中使用的插件会自动继承这里定义的版本信息。
在每个子模块的 pom.xml 文件中,需要指定父项目,典型的配置如下:
<project xmlns="http://maven.apache.org/POM/4.0.0" ...>
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.example</groupId>
<artifactId>my-multi-module-project</artifactId>
<version>1.0.0</version>
<relativePath>../pom.xml</relativePath> <!-- 指向父项目 POM -->
</parent>
<artifactId>module-a</artifactId>
<dependencies>
<!-- 子模块的依赖项 -->
</dependencies>
</project>
<parent>
:指定父项目的信息,子模块可以继承父项目中的配置。<relativePath>
:指定父项目 POM 文件的相对路径(默认是 ../pom.xml,也可以省略)。
构件坐标中的<groupId>
和<version>
都可以不用设置,直接继承父项目即可,子项目只需要配置<artifactId>
。
9.2 继承机制
在 Maven 的父子模块结构中,子模块可以继承父模块中许多配置内容。通过这种继承机制,可以减少子模块的重复配置,使得项目管理更加简洁统一。
可以继承的配置:
- 依赖管理:在父模块的
<dependencyManagement>
中定义的依赖版本,子模块中引用同样的依赖时可以不必指定版本。子模块会自动使用父模块中定义的依赖版本。 这种管理方式可以保证所有子模块中依赖的版本一致,便于控制和管理。 - 插件管理:父模块中
<pluginManagement>
定义的插件版本和配置会被子模块继承。子模块使用这些插件时无需再次指定版本,直接继承父模块的插件版本和配置。 - 发布管理在父模块中定义
<distributionManagement>
,指定构件和站点发布的仓库位置,子模块可以继承这些发布配置。 - 仓库管理:父模块中定义的
<repositories>
和<pluginRepositories>
会被子模块继承,这样可以统一定义公共仓库地址,而无需在每个子模块中重复定义。 - 属性管理:父模块中的
<properties>
中定义的属性可以在子模块中引用。例如,可以定义全局的java.version
、encoding
等属性,子模块可以直接引用这些属性,便于统一管理和修改。 - 坐标信息:包括
<groupId>
、<version>
等,如果子模块没有显式指定这些字段,会默认继承父模块中的设置。<artifactId>
通常在子模块中独立定义,不继承父模块。 - 构建配置:父模块中的
<build>
元素内的部分配置可以被子模块继承,比如资源过滤(resource filtering)、默认的目标目录(target directory)等。子模块也可以覆盖父模块中的这些构建配置,以满足特定需求。 - 配置分组:父模块中的
<profiles>
定义的构建配置文件会被子模块继承,子模块可以使用或覆盖这些配置文件。
通过继承机制,父模块可以为子模块统一管理依赖、插件、属性等配置,从而简化了子模块的配置,使得多模块项目的管理更加方便和一致。同时,子模块也可以根据需要覆盖父模块的部分配置,实现灵活性和统一性的平衡。
注意:父项目中的依赖配置
<dependencies>
是不会被继承的,只有依赖管理<dependencyManagement>
才会被继承。