1. 概述

在这个教程中,我们将了解Maven的父项目POM解析。首先,我们将了解默认行为,然后讨论如何自定义它。

2. 默认父项目POM解析

如果我们想指定一个父项目POM,可以通过命名groupIdartifactIdversion,即所谓的GAV坐标来实现。Maven不会先在仓库中搜索父项目POM。更多细节可以在Maven模型文档中找到,其行为可以总结如下:

  1. 如果父目录下有一个名为pom.xml的文件,并且该文件具有匹配的GAV坐标,那么它将被分类为项目的父POM。
  2. 如果没有,Maven会退回到仓库进行查找。

在一个Maven多模块项目管理中,将一个Maven项目放入另一个项目是最佳实践。例如,我们有一个聚合项目,其GAV坐标为:

<groupId>com.baeldung.maven-parent-pom-resolution</groupId>
<artifactId>aggregator</artifactId>
<version>1.0.0-SNAPSHOT</version>

然后,我们可以将模块放入子文件夹中,并将聚合器作为父项目引用:

模块1

因此,模块1的pom.xml可能包含以下部分:

<artifactId>module1</artifactId>
<parent>
    <groupId>com.baeldung.maven-parent-pom-resolution</groupId>
    <artifactId>aggregator</artifactId>
    <version>1.0.0-SNAPSHOT</version>
</parent>

不需要将聚合器POM安装到仓库中,甚至也不需要在聚合器POM中声明module1。但需要注意的是,这仅适用于本地项目检查出(如构建项目)时。如果项目是从Maven仓库作为依赖项解析的,那么父POM也应该在仓库中可用。

我们必须确保聚合器POM具有匹配的GAV坐标。否则,我们将得到构建错误:

[ERROR]     Non-resolvable parent POM for com.baeldung.maven-parent-pom-resolution:module1:1.0.0-SNAPSHOT:
  Could not find artifact com.baeldung.maven-parent-pom-resolution:aggregator:pom:1.0-SNAPSHOT
  and 'parent.relativePath' points at wrong local POM @ line 7, column 13

3. 自定义父项目POM的位置

如果父项目POM不在父文件夹中,我们需要使用relativePath标签来引用位置。例如,如果我们有一个第二个模块,希望从module1继承设置,而不是从聚合器开始,我们必须命名相邻的文件夹:

模块2

<artifactId>module2</artifactId>
<parent>
    <groupId>com.baeldung.maven-parent-pom-resolution</groupId>
    <artifactId>module1</artifactId>
    <version>1.0.0-SNAPSHOT</version>
    <relativePath>../module1/pom.xml</relativePath>
</parent>

当然,我们应该只使用在所有环境中都可用的相对路径(通常是同一Git仓库内的路径),以确保构建的可移植性。

4. 禁用本地文件解析

要跳过本地文件搜索,直接在Maven仓库中搜索父项目POM,我们需要明确设置relativePath为空值:

<parent>
    <groupId>com.baeldung</groupId>
    <artifactId>external-project</artifactId>
    <version>1.0.0-SNAPSHOT</version>
    <relativePath/>
</parent>

外部

这应该是在继承外部项目(如Spring Boot)时的最佳实践。

5. IDEs

有趣的是,IntelliJ IDEA(当前版本:2021.1.3)随附的Maven插件在处理父项目POM解析时与外部Maven运行时有所不同。它偏离了Maven的POM schema,对relativePath标签的解释如下:

[…] Maven首先会在当前正在构建项目的反应器中查找父pom […]

这意味着对于IDE内部解析,只要父项目注册为IntelliJ Maven项目,父POM的位置并不重要。这可能有助于我们在不显式构建项目的情况下简单地开发项目(如果它们不在同一Git仓库的范围内)。但是,如果我们尝试使用外部Maven运行时构建项目,它将失败。

6. 总结

在这篇文章中,我们了解到Maven不会首先在仓库中搜索父项目POM。它更倾向于在本地查找,而且在继承外部项目时,我们需要明确禁用这种行为。此外,IDE可能会额外解析工作空间中的项目,这可能导致当我们使用外部Maven运行时时出现错误。

如往常一样,示例代码可在GitHub上获取。