如果 child 的 pom 版本与 parent 的聚合器 pom 及其子模块的版本不同,避免错误的版本插值

Avoid wrong version interpolation if child's pom version is different from those of the parent's aggregator pom and its sub modules

问题描述

我们有一个 Maven 聚合器 pom,其中一些 child 个 poms(模块)都具有相同的版本:

pom.xml (parent zoo, version 2.0.0)
|-- pom.xml (child module cat, version 2.0.0)
|-- pom.xml (child module dog, version 2.0.0)
|-- ...

在依赖管理部分,所有 children 都用项目版本声明,以简化依赖声明。 parent pom 看起来像

<groupId>com.acme</groupId>
<artifactId>zoo</artifactId>
<version>2.0.0</version>
<packaging>pom</packaging>

<modules>
  <module>cat</module>
  <module>dog</module>
</modules>

<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>com.acme</groupId>
      <artifactId>cat</artifactId>
      <version>${project.version}</version>
    </dependency>
    <!-- other child modules go here -->
  </dependencies>
</dependencyManagement>

child poms 定义为

<parent>
  <groupId>com.acme</groupId>
  <artifactId>zoo</artifactId>
  <version>2.0.0</version>
</parent>

<groupId>com.acme</groupId>
<artifactId>cat</artifactId>

<dependencies>
  <dependency>
    <groupId>com.acme</groupId>
    <artifactId>dog</artifactId>
  </dependency>
</dependencies>

还有另一个 pom 也将 parent pom 声明为它的 parent(继承),但未在此 parent 中列为子模块(无聚合)。这个 pom 有不同的版本。

<parent>
  <groupId>com.acme</groupId>
  <artifactId>zoo</artifactId>
  <version>2.0.0</version>
</parent>

<groupId>com.acme</groupId>
<artifactId>boo</artifactId>
<version>1.0.0</version>

<dependencies>
  <dependency>
    <groupId>com.acme</groupId>
    <artifactId>dog</artifactId>
  </dependency>
</dependencies>

实际上我们已经预料到 com.acme.dog 的依赖版本是从 parent pom com.acme.zoo 的依赖管理部分拉取的,并且等于 2.0.0。但是 Maven documentation on project interpolation and variables

One factor to note is that these variables are processed after inheritance as outlined above. This means that if a parent project uses a variable, then its definition in the child, not the parent, will be the one eventually used.

即:在反应器构建中,parent pom com.acme.zoo 的依赖管理部分中使用的变量 ${project.version} 是相对于 com.acme.bar 进行评估的,等于1.0.0 不符合预期的地方。

备注

有一个解决方法是在 parent pom 中使用变量,该变量必须与 parent pom 版本保持同步。但是,此解决方案与 Maven Release Plugin.

不兼容

问题

我们怎样才能达到预期的效果

没有项目插值变量的陷阱?

最简单的解决办法是修改zoo的pom,把<version>${project.version}</version>换成<version>2.0.0</version>

请注意:

  1. 当您将版本更改为下一个数字时,例如 2.0.1,使用 versions-maven-plugin,依赖管理部分也会 已更新。

  2. Spring 使用最简单的解决方案,请参阅 http://central.maven.org/maven2/org/springframework/spring-framework-bom/4.2.7.RELEASE/spring-framework-bom-4.2.7.RELEASE.pom

总结:在依赖管理中使用<version>${project.version}</version>是错误的想法。

从 Maven 到 pom 的介绍:http://maven.apache.org/guides/introduction/introduction-to-the-pom.html

项目继承 > 示例 1 > 解决方案

Alternatively, if we want the groupId and / or the version of your modules to be the same as their parents, you can remove the groupId and / or the version identity of your module in its POM.

<project>
  <parent>
    <groupId>com.mycompany.app</groupId>
    <artifactId>my-app</artifactId>
    <version>1</version>
  </parent>
  <modelVersion>4.0.0</modelVersion>
  <artifactId>my-module</artifactId>
</project>

maven 发布插件能够更改 parent pom 中管理的依赖项的版本。

所以如果你像这样定义你的 maven parent:

<groupId>com.acme</groupId>
<artifactId>zoo</artifactId>
<version>2.0.0-SNAPSHOT</version>
<packaging>pom</packaging>

<modules>
  <module>cat</module>
  <module>dog</module>
</modules>

<dependencyManagement>
 <dependencies>
   <dependency>
     <groupId>com.acme</groupId>
     <artifactId>cat</artifactId>
     <version>2.0.0-SNAPSHOT</version>
   </dependency>
   <!-- other child modules go here -->
 </dependencies>
</dependencyManagement>

如您所见,parent 和托管依赖项的版本相同。我将它们设置为 SNAPSHOT 版本,因为发布插件将在 release:perform

上创建最终版本

您的 child poms 可以保持原样。

因为在您的设置中,您的 parent 项目也是您可以调用的反应堆

mvn release:perform -DautoVersionSubmodules=true

这将在您 运行 此命令时更新所有子模块中 parent 的版本。该选项与 运行

基本相同
mvn versions:update-child-modules

意味着它将改变 child poms。

在您 运行 mvn release:perform 命令之后,您的 parent pom 将如下所示:

<groupId>com.acme</groupId>
<artifactId>zoo</artifactId>
<version>2.0.1-SNAPSHOT</version>
<packaging>pom</packaging>

<modules>
  <module>cat</module>
  <module>dog</module>
</modules>

<dependencyManagement>
 <dependencies>
   <dependency>
     <groupId>com.acme</groupId>
     <artifactId>cat</artifactId>
     <version>2.0.1-SNAPSHOT</version>
  </dependency>
  <!-- other child modules go here -->
 </dependencies>
</dependencyManagement>

你的 child poms 是这样的

<parent>
  <groupId>com.acme</groupId>
  <artifactId>zoo</artifactId>
  <version>2.0.1-SNAPSHOT</version>
</parent>

<groupId>com.acme</groupId>
<artifactId>cat</artifactId>

<dependencies>
  <dependency>
    <groupId>com.acme</groupId>
    <artifactId>dog</artifactId>
  </dependency>
</dependencies>

最终版本将仅存在于由 release:prepare 命令创建的标签中。

PS:在运行执行release:prepare命令后提示时,您可以为最终版本和下一个开发版本定义其他版本。