Use the Latest Version of a Dependency in Maven – 在Maven中使用某个依赖的最新版本

最后修改: 2018年 10月 11日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

Upgrading Maven dependencies manually has always been a tedious work, especially in projects with a lot of libraries releasing frequently.

手动升级Maven的依赖性一直是一项繁琐的工作,尤其是在有大量库频繁发布的项目中。

In this tutorial, we’ll learn how to exploit the Versions Maven Plugin to keep our dependencies up-to-date.

在本教程中,我们将学习如何利用Maven的版本插件来保持我们的依赖关系是最新的

Above all, this can be extremely useful when implementing Continuous Integration pipelines that automatically upgrade the dependencies, test that everything still works properly, and commit or rollback the result, whichever is appropriate.

最重要的是,在实施持续集成管道时,这可能是非常有用的,它可以自动升级依赖关系,测试所有东西是否仍然正常工作,并提交或回滚结果,以适当的方式为准。

2. Maven Version Range Syntax

2.Maven版本范围语法

Back in the Maven2 days, developers could specify version ranges within which the artifacts would’ve been upgraded without the need of a manual intervention.

在Maven2时代,开发者可以指定版本范围,在此范围内,工件将被升级,而不需要人工干预。

This syntax is still valid, used in several projects out there and is hence worth knowing:

这种语法仍然有效,在外面的一些项目中使用,因此值得了解。

Maven Version Range Syntax

Nonetheless, we should avoid it in favor of the Versions Maven Plugin when possible, because advancing concrete versions from the outside gives us definitely more control than letting Maven handle the whole operation on its own.

尽管如此,我们还是应该避免使用它,尽可能使用Maven的版本插件,因为从外部推进具体的版本,绝对比让Maven自己处理整个操作更有控制力。

2.1. Deprecated Syntax

2.1.废弃的语法

Maven2 also provided two special metaversion values to achieve the result: LATEST and RELEASE.

Maven2还提供了两个特殊的元反转值来实现这一结果。LATESTRELEASE

LATEST looks for the newest possible version, while RELEASE aims at the latest non-SNAPSHOT version.

LATEST寻找可能的最新版本,而RELEASE旨在寻找最新的非SNAPSHOT版本。

They’re, indeed, still absolutely valid for regular dependencies resolution.

事实上,他们仍然是绝对的有效的常规依赖关系解决方案。

However, this legacy upgrade method was causing unpredictability where CI needed reproducibility. Hence, they’ve been deprecated for plugin dependencies resolution.

然而,这种传统的升级方法在CI需要重现性的地方造成了不可预测性。因此,它们已被废弃,用于解决插件依赖性问题

3. Versions Maven Plugin

3.版本Maven插件

The Versions Maven Plugin is the de facto standard way to handle versions management nowadays.

Versions Maven Plugin是目前处理版本管理的事实上的标准方法。

From high-level comparisons between remote repositories up to low-level timestamp-locking for SNAPSHOT versions, its massive list of goals allows us to take care of every aspect of our projects involving dependencies.

从远程存储库之间的高级比较到SNAPSHOT版本的低级时间戳锁定,其庞大的目标列表使我们能够照顾到项目中涉及依赖关系的各个方面。

While many of them are out of the scope of this tutorial, let’s take a closer look at the ones that will help us in the upgrade process.

虽然其中很多都不在本教程的范围内,但让我们仔细看看那些对我们的升级过程有帮助的内容。

3.1. The Test Case

3.1.测试案例

Before starting, let’s define our test case:

在开始之前,让我们定义我们的测试案例。

  • three RELEASEs with a hard-coded version
  • one RELEASE with a property version, and
  • one SNAPSHOT
<dependencies>
    <dependency>
        <groupId>commons-io</groupId>
        <artifactId>commons-io</artifactId>
        <version>2.3</version>
    </dependency>
    <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-collections4</artifactId>
        <version>4.0</version>
    </dependency>
    <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-lang3</artifactId>
        <version>3.0</version>
    </dependency>
    <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-compress</artifactId>
        <version>${commons-compress-version}</version>
    </dependency>
    <dependency>
        <groupId>commons-beanutils</groupId>
        <artifactId>commons-beanutils</artifactId>
        <version>1.9.1-SNAPSHOT</version>
    </dependency>
</dependencies>

<properties>        
    <commons-compress-version>1.15</commons-compress-version>
</properties>

Finally, let’s also exclude an artifact from the process when defining the plugin:

最后,让我们在定义插件的过程中也排除掉一个人工制品。

<build>
    <plugins>
        <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>versions-maven-plugin</artifactId>
            <version>2.7</version>
            <configuration>
                <excludes>
                    <exclude>org.apache.commons:commons-collections4</exclude>
                </excludes>
            </configuration>
        </plugin>
    </plugins>
</build>

4. Displaying Available Updates

4.显示可用的更新

First of all, to simply know if and how we can update our project, the right tool for the job is versions:display-dependency-updates:

首先,要简单地知道我们是否可以更新项目以及如何更新,正确的工具是versions:display-dependency-updates

mvn versions:display-dependency-updates

mvn versions:display-dependency-updates

As we can see, the process included every RELEASE version. It even included commons-collections4 since the exclusion in the configuration refers to the update process, and not to the discovery one.

正如我们所看到的,该进程包括了每个 RELEASE 版本。它甚至包括了commons-collections4,因为配置中的排除法是指更新过程,而不是发现过程。

In contrast, it ignored the SNAPSHOT, for the reason that it’s a development version which is often not safe to update automatically.

相比之下,它忽略了SNAPSHOT,原因是它是一个开发版本,自动更新往往不安全。

5. Updating the Dependencies

5.更新依赖关系

When running an update for the first time, the plugin creates a backup of the pom.xml named pom.xml.versionsBackup.

当第一次运行更新时,该插件创建了一个名为pom.xml的备份,名为pom.xml.versionBackup

While every iteration will alter the pom.xml, the backup file will preserve the original state of the project up to the moment the user will commit (through mvn versions:commit) or revert (through mvn versions:revert) the whole process.

虽然每次迭代都会改变pom.xml,但备份文件将保留项目的原始状态,直到用户提交(通过mvn <>versions:commit)或还原(通过mvn <>versions:revert)整个过程的时刻。

5.1. Converting SNAPSHOTs into RELEASEs

5.1.将SNAPSHOT转换为RELEASE

It happens sometimes that a project includes a SNAPSHOT (a version which is still under heavy development).

有时会发生这样的情况,一个项目包括一个SNAPSHOT(一个仍在大力开发的版本)。

We can use versions:use-releases to check if the correspondent RELEASE has been published, and even more to convert our SNAPSHOT into that RELEASE at the same time:

我们可以使用versions:use-releases来检查对应的RELEASE是否已经发布,更可以同时将我们的SNAPSHOT转换成该RELEASE。

mvn versions:use-releases

mvn versions:use-releases

5.2. Updating to the Next RELEASE

5.2.更新到下一个RELEASE

We can port every non-SNAPSHOT dependency to its nearest version with versions:use-next-releases:

我们可以通过versions:use-next-releases将每个非SNAPSHOT的依赖关系移植到其最近的版本

mvn versions:use-next-releases

mvn versions:use-next-releases

We can clearly see that the plugin updated commons-io, commons-lang3, and even commons-beanutils, which is not a SNAPSHOT anymore, to their next version.

我们可以清楚地看到,该插件将commons-iocommons-lang3,甚至commons-beanutils(不再是SNAPSHOT)更新到它们的下一个版本。

Most importantly, it ignored commons-collections4, which is excluded in the plugin configuration, and commons-compress, which has a version number specified dynamically through a property.

最重要的是,它忽略了commons-collections4,它在插件配置中被排除,以及commons-compress,它的版本号通过属性动态指定。

5.3. Updating to the Latest RELEASE

5.3.更新到最新的RELEASE

Updating every non-SNAPSHOT dependency to its latest release works in the same way, simply changing the goal to versions:use-latest-releases:

将每一个非SNAPSHOT的依赖关系更新到其最新版本的工作方式相同,只需将目标改为versions:use-latest-releases

mvn versions:use-latest-releases

mvn versions:use-latest-releases

6. Filtering out Unwanted Versions

6.过滤掉不需要的版本

In case we want to ignore certain versions, the plugin configuration can be tuned to dynamically load rules from an external file:

如果我们想忽略某些版本,插件配置可以进行调整,从外部文件动态加载规则。

<plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>versions-maven-plugin</artifactId>
    <version>2.7</version>
    <configuration>
        <rulesUri>http://www.mycompany.com/maven-version-rules.xml</rulesUri>
    </configuration>
</plugin>

Most noteworthy, <rulesUri> can also refer to a local file:

最值得注意的是,<rulesUri>也可以指代一个本地文件。

<rulesUri>file:///home/andrea/maven-version-rules.xml</rulesUri>

6.1. Ignoring Versions Globally

6.1.在全球范围内忽略版本

We can configure our rules file so that it’ll ignore versions matching a specific Regular Expression:

我们可以配置我们的规则文件,以便它将忽略匹配特定正则表达式的版本

<ruleset comparisonMethod="maven"
  xmlns="http://mojo.codehaus.org/versions-maven-plugin/rule/2.0.0"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://mojo.codehaus.org/versions-maven-plugin/rule/2.0.0 
  http://mojo.codehaus.org/versions-maven-plugin/xsd/rule-2.0.0.xsd">
    <ignoreVersions>
        <ignoreVersion type="regex">.*-beta</ignoreVersion>
    </ignoreVersions>
</ruleset>

6.2. Ignoring Versions on a Per-Rule Basis

6.2.在每条规则的基础上忽略版本

Finally, in case our needs are more specific, we can build a set of rules instead:

最后,如果我们的需求更加具体,我们可以建立一套规则来代替。

<ruleset comparisonMethod="maven"
  xmlns="http://mojo.codehaus.org/versions-maven-plugin/rule/2.0.0"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://mojo.codehaus.org/versions-maven-plugin/rule/2.0.0 
    http://mojo.codehaus.org/versions-maven-plugin/xsd/rule-2.0.0.xsd">
    <rules>
        <rule groupId="com.mycompany.maven" comparisonMethod="maven">
            <ignoreVersions>
                <ignoreVersion type="regex">.*-RELEASE</ignoreVersion>
                <ignoreVersion>2.1.0</ignoreVersion>
            </ignoreVersions>
        </rule>
    </rules>
</ruleset>

7. Conclusion

7.结论

We’ve seen how to check and update the dependencies of a project in a safe, automatic, and Maven3-compliant way.

我们已经看到如何以安全、自动、符合Maven3标准的方式检查和更新项目的依赖关系。

As always, the source code is available over on GitHub, along with a script to help showcase everything step-by-step and without complexity.

一如既往,源代码可在GitHub上获得,同时还有一个脚本,以帮助逐步展示一切,不至于太复杂。

To see it in action, simply download the project and run in a terminal (or in Git Bash if using Windows):

要看它的运行情况,只需下载该项目并在终端运行(如果使用Windows,则在Git Bash中运行)。

./run-the-demo.sh