1. 概述
在这个教程中,我们将了解Maven的父项目POM解析。首先,我们将了解默认行为,然后讨论如何自定义它。
2. 默认父项目POM解析
如果我们想指定一个父项目POM,可以通过命名groupId
、artifactId
和version
,即所谓的GAV坐标
来实现。Maven不会先在仓库中搜索父项目POM。更多细节可以在Maven模型文档中找到,其行为可以总结如下:
- 如果父目录下有一个名为
pom.xml
的文件,并且该文件具有匹配的GAV坐标,那么它将被分类为项目的父POM。 - 如果没有,Maven会退回到仓库进行查找。
在一个Maven多模块项目管理中,将一个Maven项目放入另一个项目是最佳实践。例如,我们有一个聚合项目,其GAV坐标为:
<groupId>com.baeldung.maven-parent-pom-resolution</groupId>
<artifactId>aggregator</artifactId>
<version>1.0.0-SNAPSHOT</version>
然后,我们可以将模块放入子文件夹中,并将聚合器作为父项目引用:
因此,模块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
继承设置,而不是从聚合器开始,我们必须命名相邻的文件夹:
<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上获取。