您现在的位置是:首页 >技术杂谈 >【工具篇】Maven使用${revision}实现多模块版本统一管理网站首页技术杂谈

【工具篇】Maven使用${revision}实现多模块版本统一管理

光阴迷客 2024-10-24 12:01:04
简介【工具篇】Maven使用${revision}实现多模块版本统一管理

背景说明

在使用Maven多模块结构工程时,版本管理是一件很繁琐且容易出错的事情。每次升级版本号都要手动调整或者通过mvn versions:set -DnewVerion=xx命令去更改每一个子模块的版本号,非常的不方便,而且会改动所有的模块,出现如下效果:
在这里插入图片描述

解决方法

其实Maven已经提供了这种CI版本的管理方式,下面来介绍一下具体使用方法。

Maven官方文档说:自 Maven 3.5.0-beta-1 开始,可以使用 ${revision}, ${sha1} and/or ${changelist} 这样的变量作为版本占位符。

即在maven多模块项目中,可配合插件flatten-maven-plugin${revision}属性来实现全局版本统一管理。

环境说明

Maven Version:Apache Maven 3.5.0-beta-1及以上版本
Maven Plugin:flatten-maven-plugin
IDE: IntelliJ IDEA 2021.3
JDK: 1.8.0_301
POM文件:使用占位符${revision}

注意事项

① 只能命名成revision,不可以更改成其他命名;
② Idea下使用${revision}定义Parent版本时会提示错误“Reports that usage of properties in modules parent definition is prohibited”,但并不影响使用,只是Idea不支持这种写法而已,升级IDea版本也可以解决 【可忽略】

代码示例

父模块配置

在properties标签中定义revision标签:

<project>
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.4.RELEASE</version>
        <relativePath/>
    </parent>

    <groupId>org.sssss.maven</groupId>
    <artifactId>sssss-parent</artifactId>
    <version>${revision}</version>
    <packaging>pom</packaging>

    <properties>
        <!-- 全局版本控制,如果要修改版本号,修改此处即可-->
        <revision>1.0.0-SNAPSHOT</revision>
    </properties>

    <modules>
        <module>sssss-child1</module>
        ...
    </modules>

    <build>
        <plugins>
            <!-- 添加flatten-maven-plugin插件 -->
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>flatten-maven-plugin</artifactId>
                <version>1.5.0</version>
                <executions>
                    <execution>
                        <id>flatten</id>
                        <phase>process-resources</phase>
                        <goals>
                            <goal>flatten</goal>
                        </goals>
                    </execution>
                    <execution>
                        <id>flatten.clean</id>
                        <phase>clean</phase>
                        <goals>
                            <goal>clean</goal>
                        </goals>
                    </execution>
                </executions>
                <inherited>true</inherited>
                <configuration>
                    <!-- 避免IDE将 .flattened-pom.xml 自动识别为功能模块 -->
                    <updatePomFile>true</updatePomFile>
                    <flattenMode>resolveCiFriendliesOnly</flattenMode>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

关键点:
① 父子模块需遵循父子目录层次;
② 在父模块中引入插件flatten-maven-plugin
③ 修改.gitignore文件,增加一行.flattened-pom.xml
④ 不可混合使用${revision}和明确字符串版本号,若出现父子模块版本号混合使用${revision}和明确字符串形式如1.0.0.-SNAPSHOT,在mvn package会出现类似如下错误:

[FATAL] Non-resolvable parent POM for org.sssss.maven:child1:[unknown-version]:
Could not find artifact org.sssss.maven:sssss-parent:pom:1.0.0-SNAPSHOT and ‘parent.relativePath’ points at wrong local POM @ line 5, column 13

关于子模块中parent.relativePath使用:

  • 默认值,不设置relativePath即为默认值,等价于<relativePath>../pom.xml</relativePath>,即遵循父子目录层次
    • 即优先查找上层目录…/pom.xml
    • 然后查找本地仓库
    • 最后查找远程仓库
    • 推荐自定义的开发项目遵循此种方式(即父子模块需遵循父子目录层次,且保持parent.relativePath的默认值)
  • 空值,即跳过本地文件目录查找
    • 直接查找本地仓库
    • 最后查找远程仓库
    • 适用于父依赖为第三方公有仓库中的依赖,如spring-boot-starter-parent
  • 其他值,可根据目录层次自行定义(推荐使用相对目录层次),如<relativePath>../module-1/pom.xml</relativePath>

子模块配置

子模块可以直接使用${revision}指定父模块的版本:

<project>
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.sssss.maven</groupId>
        <artifactId>sssss-parent</artifactId>
        <version>${revision}</version>
        <relativePath>../pom.xml</relativePath> <!-- 可忽略 -->
    </parent>

    <artifactId>sssss-child1</artifactId>
    <packaging>jar</packaging>

</project>

子模块依赖

多模块工程结构下,会有子模块相互依赖的情况,使用${revision}会导致构建失败,应该使用${project.version}来定义依赖 (同父工程下的依赖) 的版本,请勿使用${parent.version}

<project>
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.sssss.maven</groupId>
        <artifactId>sssss-parent</artifactId>
        <version>${revision}</version>
        <relativePath>../pom.xml</relativePath> <!-- 可忽略 -->
    </parent>

    <artifactId>sssss-child2</artifactId>
    <packaging>jar</packaging>
    
    <dependencies>
        <dependency>
            <groupId>org.sssss.maven</groupId>
            <artifactId>child1</artifactId>
            <version>${project.version}</version>
      </dependency>
  </dependencies>

install / depoy

执行install/deploy后,会将该模块的pom文件中的${revision}替换为实际的版本,每个模块下都会生成一个.flattened-pom.xml文件。

基于以上操作,每次版本号变更,只需要修改父模块POM文件中的revision即可。还可以用另一种动态添加参数的方式来指定版本:

mvn clean install -Drevision=1.0.0-SNAPSHOT  # -D代表设置环境变量

参考文章

maven-ci-friendly
flatten-maven-plugin
spring-boot-project
maven-relativepath
Maven多模块结构下版本管理的正确姿势

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。