Maven 模块版本管理

项目中常用的一些公共组件是独立开发的,但版本却没有有效管理,导致在构建使用中问题频发,一番折腾后发现 Maven 官方已经提供了版本控制的最佳实践,下面就来一起看看。

前提

原文名为 Maven CI Friendly Versions 意为 CI 版本友好,从 3.5.0-beta-1 开始,Maven 支持使用 ${revision} 作为 pom 文件中版本的占位符,IDEA 会报错但不影响使用。

单模块项目

如下是一个常规的工程

1
2
3
4
5
6
7
8
9
10
11
12
13
<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} 占位符,有如下两种方式可以指定版本

命令行

mvn 参数指定的方式

1
mvn -Drevision=1.0.0-SNAPSHOT clean package

示例便是指定 revision 为 1.0.0-SNAPSHOT 为构建版本

属性配置

也可以可以在 pom.xml 文件中指定版本属性配置达到相同的效果

1
2
3
4
5
6
<project>
...
<properties>
<revision>1.0.0-SNAPSHOT</revision>
</properties>
</project>

多模块项目

父项目

例如我们可能有一个多模块项目,项目的 parent pom 应当像这样

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<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>
<module>child2</module>
..
</modules>
</project>

延续之前 version 设置为 ${revision} 占位符

子模块

子模块应该是如下这种模式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<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>child1</artifactId>
...
<dependencies>
<dependency>
<groupId>org.apache.maven.ci</groupId>
<artifactId>child2</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</project>

子模块配置中值得注意的有两点:

  • parent version 引用 ${revision}
  • 对其他子模块的 version 引用 ${project.version}

Install / Deploy

以上内容发布在 Maven 私服上是无法被其他项目引用的,还需要配合 flatten-maven-plugin 插件进行处理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<project>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>flatten-maven-plugin</artifactId>
<version>1.2.7</version>
<configuration>
<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>
</project>

flatten 工作时会替换 pom 中的占位符,让 pom 变的完整可用,前面提到的 IDEA 报错也会在 Install 之后消除。

SNAPSHOT 版本

SNAPSHOT 意为快照,用来表示不稳定的开发版本,建议开发过程中版本号加上-SNAPSHOT,在预发布时去掉或替换为 -RELEASE

使用-SNAPSHOT的好处就是开发过程中版本号不用频繁修改,减少模块依赖方的使用负担,那么模块依赖方如何使用呢?

  • Idea 中勾选 File | Settings | Build, Execution, Deployment | Build Tools | Maven 中的 Always update snapshot
  • Maven 命令行使用时需加 -U 例如:mvn package -U

上述操作可以保证在使用过程中始终使用仓库上的最新包。

优化引用

如果模块较多会也会对依赖方造成困扰,这时可以新增 bom 模块,用于对子模块进行统一管理, parent pom :

1
2
3
4
5
6
7
8
9
<project>
...
<modules>
<module>child1</module>
<module>child2</module>
<module>child-bom</module>
..
</modules>
</project>

child-bom 则通过 dependencyManagement 引入其他全部子模块

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<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>child-bom</artifactId>
<packaging>pom</packaging>
...
<dependencyManagement>
<dependency>
<groupId>org.apache.maven.ci</groupId>
<artifactId>child1</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.maven.ci</groupId>
<artifactId>child2</artifactId>
<version>${project.version}</version>
</dependency>
</dependencyManagement>
</project>

在模块依赖方仅引用 bom 即可,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<project>
...
<dependencyManagement>
<dependency>
<groupId>org.apache.maven.ci</groupId>
<artifactId>child-bom</artifactId>
<version>${ci-project.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.apache.maven.ci</groupId>
<artifactId>child2</artifactId>
</dependency>
</dependencies>
</project>

可以看到模块依赖方在通过 dependencyManagement 引入 bom 模块,再引入 child2 可以免版本号。

写在最后

经过这样修改之后可以有效解决 Maven 版本混乱的问题,避免使用上的冲突和错误,希望可以帮到各位。