【问题标题】:Avoid wrong version interpolation if child's pom version is different from those of the parent's aggregator pom and its sub modules如果 child 的 pom 版本与 parent 的聚合器 pom 及其子模块的版本不同,请避免错误的版本插值
【发布时间】:2016-12-17 18:13:45
【问题描述】:

问题描述

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

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)
|-- ...

在依赖项管理部分中,所有子项都使用项目版本声明,以简化依赖项的声明。 父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>

子 pom 被定义为

<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 也将父 pom 声明为其父 pom(继承),但未在此父 pom 中列为子模块(无聚合)。这个 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的版本是从父pomcom.acme.zoo的依赖管理部分拉出来的,等于2.0.0。但是Maven documentation on project interpolation and variables

需要注意的一个因素是,这些变量是在继承后处理的,如上所述。这意味着如果父项目使用一个变量,那么它在子项目中的定义,而不是父项目,将是最终使用的变量。

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

注意

有一种在父 pom 中使用变量的解决方法,该变量必须与父 pom 版本保持同步。但是,此解决方案与Maven Release Plugin 不兼容。

问题

我们怎样才能实现期望的行为

  • 具有相同版本的孩子的聚合器 pom
  • 在依赖项管理部分声明子项,以确保所有依赖项具有相同的版本
  • 继承与不同版本一起使用
  • maven-release-plugin的兼容性

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

【问题讨论】:

    标签: maven pom.xml versioning parent-pom


    【解决方案1】:

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

    请注意:

    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

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

    【讨论】:

      【解决方案2】:

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

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

      或者,如果我们想要 groupId 和/或您的版本 模块与其父模块相同,您可以删除 groupId 和/或您的模块在其 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>
      

      【讨论】:

      • 问题是cat必须依赖同版本的dog。为此应用了依赖管理。你的回答不能解决依赖管理配置的问题
      • 好的。我明白你现在的意思了。在这种情况下,您可能拥有 cat 版本 1.1,其父版本为 1.0,因此 dog 的版本为 1.0。这是错误的。
      • 您从 cat 和 dog 中删除版本的提示很好,但问题不同。实际上整个动物园都有 2.0.0 版本,并且问题所有者希望猫依赖狗而没有在猫的pom.xml 中定义的版本。出于这个原因,狗的版本在动物园依赖管理部分中定义。但是版本定义为${project.version}是错误的
      【解决方案3】:

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

      所以如果你这样定义你的 maven 父级:

      <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>
      

      如您所见,父级和托管依赖项的版本是相同的。我将它们设置为 SNAPSHOT 版本,因为发布插件将在发布时创建最终版本:执行

      您的孩子 poms 可以保持原样。

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

      mvn release:perform -DautoVersionSubmodules=true
      

      当您运行此命令时,它将更新所有子模块中的父级版本。该选项与运行时基本相同

      mvn versions:update-child-modules
      

      意味着它会改变子 pom。

      运行 mvn release:perform 命令后,您的父 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>
      

      和你的孩子这样玩

      <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 命令后出现提示时,您可以为最终版本和下一个开发版本定义其他版本。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-11-12
        • 1970-01-01
        • 1970-01-01
        • 2018-03-05
        • 2017-02-22
        • 2020-07-12
        • 2017-09-14
        • 2020-08-28
        相关资源
        最近更新 更多