在使用Maven多模块结构工程时,配置版本是一个比较头疼的事。继承版本,依赖版本,自身版本,都需要单独定义,很是麻烦。
版本号变更使用mvn versions:set,有时候也可能导致版本号不一致、不便于统一管理:
mvn versions:set
但其实Maven已经提供了这种CI版本的管理方式,下面来介绍具体用法。
从Maven 3.5.0-beta-1版本开始,就可以使用${revision}
, ${sha1}
和 ${changelist}
作为占位符来替换pom文件了。
注意:Idea下使用${revision}
定义Parent版本时会提示错误“Reports that usage of properties in modules parent definition is prohibited”,但并不影响使用,只是Idea不支持这种写法而已。
单模块项目
<project>
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.apache</groupId>
<artifactId>apache</artifactId>
<version>18</version>
</parent>
<groupId>org.apache.maven.ci</groupId>
<artifactId>ci-parent</artifactId>
<name>First CI Friendly</name>
<version>${revision}</version>
...
</project>
这种情况比较简单,只使用了${revision}
来替换版本。
每次版本号变更,只需要修改即可
<properties>
<revision>1.0.0-SNAPSHOT</revision>
</properties>
还可以用另一种动态添加参数的方式来指定版本
$ mvn -Drevision=1.0.0-SNAPSHOT clean package
-D代表设置环境变量
-D,--define <arg> Define a system property
或者在(父)项目的properties中定义版本:
<project>
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.apache</groupId>
<artifactId>apache</artifactId>
<version>18</version>
</parent>
<groupId>org.apache.maven.ci</groupId>
<artifactId>ci-parent</artifactId>
<name>First CI Friendly</name>
<version>${revision}</version>
...
<properties>
<revision>1.0.0-SNAPSHOT</revision>
</properties>
</project>
多模块项目
现在来看看多模块构建的情况。有一个父项目和一个或多子模块。父pom将如下所示:
<project>
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.apache</groupId>
<artifactId>apache</artifactId>
<version>18</version>
</parent>
<groupId>org.apache.maven.ci</groupId>
<artifactId>ci-parent</artifactId>
<name>First CI Friendly</name>
<version>${revision}</version>
...
<properties>
<revision>1.0.0-SNAPSHOT</revision>
</properties>
<modules>
<module>child1</module>
..
</modules>
</project>
子模块配置:
<project>
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.apache.maven.ci</groupId>
<artifactId>ci-parent</artifactId>
<version>${revision}</version>
</parent>
<groupId>org.apache.maven.ci</groupId>
<artifactId>ci-child</artifactId>
...
</project>
多模块项目中子模块的版本应该使用父工程的版本,单独设置版本的话会导致版本混乱。
依赖
多模块工程结构下,会有很多模块依赖的情况,应该使用${project.version}来定义依赖(同父工程下的依赖)的版本
<project>
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.apache</groupId>
<artifactId>apache</artifactId>
<version>18</version>
</parent>
<groupId>org.apache.maven.ci</groupId>
<artifactId>ci-parent</artifactId>
<name>First CI Friendly</name>
<version>${revision}</version>
...
<properties>
<revision>1.0.0-SNAPSHOT</revision>
</properties>
<modules>
<module>child1</module>
..
</modules>
</project>
子工程配置:
<project>
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.apache.maven.ci</groupId>
<artifactId>ci-parent</artifactId>
<version>${revision}</version>
</parent>
<groupId>org.apache.maven.ci</groupId>
<artifactId>ci-child</artifactId>
...
<dependencies>
<dependency>
<groupId>org.apache.maven.ci</groupId>
<artifactId>child2</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</project>
定义依赖版本时,使用${revision}
会导致构建失败,需要使用${project.version}
。
install/deploy
如果使用以上设置来发布,必须使用flatten-maven-plugin
<project>
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.apache</groupId>
<artifactId>apache</artifactId>
<version>18</version>
</parent>
<groupId>org.apache.maven.ci</groupId>
<artifactId>ci-parent</artifactId>
<name>First CI Friendly</name>
<version>${revision}</version>
...
<properties>
<revision>1.0.0-SNAPSHOT</revision>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>flatten-maven-plugin</artifactId>
<version>1.1.0</version>
<configuration>
是否更新pom文件,此处还有更高级的用法
<updatePomFile>true</updatePomFile>
<flattenMode>resolveCiFriendliesOnly</flattenMode>
</configuration>
<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>
</plugin>
</plugins>
</build>
<modules>
<module>child1</module>
..
</modules>
</project>
最终执行install/deploy后,会将该模块的pom文件中的${revision}
替换为实际的版本。
maven:读取程序版本号的三种方案
方案1
在应用项目中,如果应用程序需要获取当前程序的版本号,可以读取”/META-INF/maven/${groupId}/${artifactId}/pom.properties“,获取maven生成的版本信息。
当然前提用应用程序在运行时得知道自己的groupId和artifactId,否则无法定位路径。
pom.properties内容示例
#Created by Apache Maven .5.0 version=1.0.4-SNAPSHOT groupId=com.gitee.l0km artifactId=facelog-service
这种方法很简单,但也有缺点:
貌似这种方法只能获取maven默认定义${project.version},无法加入自定义的信息。
方案2
还有一个方案就是直接将版本信息写入MANIFEST.MF。通过java.util.jar.Manifest来读取解析MANIFEST.MF来获取版本号。
如下增加buildnumber-maven-plugin插件,并给maven-jar-plugin插件指定写入MANIFEST.MF的参数。
<plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>buildnumber-maven-plugin</artifactId> <version>1.2</version> <executions> <execution> <goals> <goal>create</goal> </goals> </execution> </executions> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jar-plugin</artifactId> <version>3.0.2</version> <configuration> <archive> <manifestEntries> <!-- 项目版本号 --> <Project-Version>${project.version}</Project-Version> <!-- buildnumber插件提供的 SCM(git/svn等)版本号 --> <Scm-Version>${buildNumber}</Scm-Version> <!-- 时间戳 --> <Timestamp>${maven.build.timestamp}</Timestamp> </manifestEntries> </archive> </configuration> </plugin>
方案3
前面两种方案,都需要将应用程序打成jar包才能读取版本信息。
那么程序在开发调试的时候,并没有生成pom.properties,和MANIFEST.MF,也就无法读取版本信息了。
所以另一种思路就是用 template-maven-plugin插件让maven自动生成一个包含版本信息的代码如Version.java。这样任何时候,程序都能很方便的知道自己的版本号了。
模板
首先需要一个代码模板Version.java,示例如下:
package net.gdface.facelog.service; public final class Version { /** project version */ public static final String VERSION = "${project.version}"; /** SCM(git) revision */ public static final String SCM_REVISION= "${buildNumber}"; /** SCM branch */ public static final String SCM_BRANCH = "${scmBranch}"; /** build timestamp */ public static final String TIMESTAMP ="${buildtimestamp}"; }
模板放在/src/main/java/java-templates/${package_of_template}/下
原本在模板文件中用maven内置变量${maven.build.timestamp}做时间戳,实际运行并没有被正确替换,不知道原因。所以改为使用buildnumber-maven-plugin插件(goal create-timestamp)生成的时间戳${buildtimestamp}
插件
然后修改pom.xml增加 template-maven-plugin插件和buildnumber-maven-plugin插件
<plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>buildnumber-maven-plugin</artifactId> <version>1.4</version> <executions> <execution> <id>bn1</id> <goals> <!-- 创建${buildNumber} --> <goal>create</goal> </goals> </execution> <execution> <id>bn2</id> <goals> <!-- 创建时间戳${buildtimestamp} --> <goal>create-timestamp</goal> </goals> <configuration> <!-- 指定时间戳变量名 --> <timestampPropertyName>buildtimestamp</timestampPropertyName> <!-- 指定日期格式 --> <timestampFormat>yyyy-MM-dd HH:mm:ss</timestampFormat> </configuration> </execution> </executions> </plugin> <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>templating-maven-plugin</artifactId> <version>1.0.0</version> <executions> <execution> <id>filter-src</id> <goals> <goal>filter-sources</goal> </goals> </execution> </executions> </plugin>
template-maven-plugin插件会将/src/main/java/java-templates/文件夹下的所有模板中的${xxx}占位符都用maven中同名的变量替换一遍,
生成的Version.java在${project.build.directory}/generated-sources/${package_of_template}下,并且该文件夹会自动成为源码文件夹加入编译过程。
参考
https://maven.apache.org/maven-ci-friendly.html
https://github.com/spring-projects/spring-boot
https://www.mojohaus.org/flatten-maven-plugin/
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/13967.html