如何告诉 Maven 使用最新版本的依赖项?
在 Maven 中,依赖关系通常是这样设置的:
<dependency>
<groupId>wonderful-inc</groupId>
<artifactId>dream-library</artifactId>
<version>1.2.3</version>
</dependency>
现在,如果您正在使用频繁发布的库,请不断更新
In Maven, dependencies are usually set up like this:
<dependency>
<groupId>wonderful-inc</groupId>
<artifactId>dream-library</artifactId>
<version>1.2.3</version>
</dependency>
Now, if you are working with libraries that have frequent releases, constantly updating the <version> tag can be somewhat annoying. Is there any way to tell Maven to always use the latest available version (from the repository)?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
发布评论
评论(12)
事实上,即使在 3.x 中它仍然有效,令人惊讶的是项目的构建和部署。 但是 LATEST/RELEASE 关键字导致 m2e 和 eclipse 到处出现问题,而且项目依赖于通过 LATEST/RELEASE 部署的依赖项,无法识别版本。
如果您尝试将版本定义为属性,并在其他地方引用它,它也会导致问题。
所以结论是如果可以的话请使用 versions-maven-plugin 。
依赖项语法位于依赖项版本要求规范文档。 这是为了完整性:
依赖项的
version
元素定义版本要求,用于计算有效的依赖项版本。 版本要求具有以下语法:
1.0
:1.0 的“软”要求(如果它与依赖项的所有其他范围匹配,则只是建议)[1.0]
:1.0 的“硬”要求(,1.0]
:x <= 1.0[1.2,1.3]
:1.2 <= x <= 1.3[1.0,2.0)
:1.0 <= x < 2.0[1.5,)
: x >= 1.5(,1.0],[1.2,)
:x <= 1.0 或 x >= 1.2; 多个集合以逗号分隔(,1.1),(1.1,)
:这不包括 1.1(例如,如果已知不
与该库结合使用)
在您的情况下,您可以执行类似
与其他人不同,我认为您可能总是想要最新版本的原因有很多。 特别是如果您正在进行持续部署(我们有时一天内发布 5 个版本)并且不想进行多模块项目。
我所做的是让 Hudson/Jenkins 对每个构建执行以下操作:
mvn clean versions:use-latest-versions scm:checkin deploy -Dmessage="update versions" -DperformRelease=true
即我使用版本插件和 scm 插件来更新依赖项,然后将其签入源代码管理。 是的,我让我的 CI 进行 SCM 签入(无论如何您都必须为 Maven 发布插件执行此操作)。
您需要设置版本插件以仅更新您想要的内容:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>versions-maven-plugin</artifactId>
<version>1.2</version>
<configuration>
<includesList>com.snaphop</includesList>
<generateBackupPoms>false</generateBackupPoms>
<allowSnapshots>true</allowSnapshots>
</configuration>
</plugin>
我使用发布插件来执行发布,它负责 -SNAPSHOT 并验证是否存在 -SNAPSHOT 的发布版本(这很重要)。
如果您执行我所做的操作,您将获得所有快照版本的最新版本和发布版本的最新发行版本。 您的构建也将是可复制的。
更新
我注意到一些评论询问了此工作流程的一些细节。 我想说的是,我们不再使用这种方法,主要原因是 Maven 版本插件存在缺陷,并且通常存在固有缺陷。
它是有缺陷的,因为要运行版本插件来调整版本,所有现有版本都需要存在才能使 pom 正确运行。 也就是说,如果版本插件找不到 pom.xml 中引用的版本,则它无法更新到任何内容的最新版本。 这实际上相当烦人,因为我们经常出于磁盘空间原因清理旧版本。
实际上,您需要一个来自 Maven 的单独工具来调整版本(这样您就不需要依赖 pom 文件来正确运行)。 我用 Bash 等低级语言编写了这样一个工具。 该脚本将像版本插件一样更新版本,并将 pom 检查回源代码管理。 它的运行速度也比 mvn versions 插件快 100 倍。 不幸的是,它不是以供公众使用的方式编写的,但如果人们感兴趣,我可以这样做并将其放在 gist 或 github 中。
回到工作流程,因为一些评论询问这就是我们所做的:
- 我们在自己的存储库中有 20 个左右的项目,有自己的 jenkins 作业,
- 当我们发布时,使用 Maven 发布插件。 插件的文档中介绍了其工作流程。 Maven 发布插件有点糟糕(我很友善),但它确实有效。 有一天,我们计划用更优化的方法替换这种方法。
- 当其中一个项目发布时,jenkins 会运行一项特殊作业,我们将调用更新所有版本作业(jenkins 如何知道其版本是一种复杂的方式,部分原因是 Maven jenkins 发布插件也非常糟糕)。
- 更新所有版本作业了解所有 20 个项目。 它实际上是一个聚合器 pom,用于按依赖顺序指定模块部分中的所有项目。 Jenkins 运行我们神奇的 groovy/bash foo,它会将所有项目更新到最新版本,然后签入 poms(再次根据模块部分按依赖顺序完成)。
- 对于每个项目,如果 pom 已更改(由于某些依赖项中的版本更改),则将其签入,然后我们立即 ping jenkins 以运行该项目的相应作业(这是为了保留构建依赖项顺序,否则您将受到怜悯SCM 轮询调度程序)。
在这一点上,我认为无论如何,将发布版和自动版作为单独的工具与您的常规构建分开是一件好事。
现在,您可能会因为上面列出的问题而认为 Maven 有点糟糕,但对于没有易于解析的声明式可扩展语法(又名 XML)的构建工具来说,这实际上会相当困难。
事实上,我们通过命名空间添加自定义 XML 属性来帮助提示 bash/groovy 脚本(例如,不要更新此版本)。
现在我知道这个主题已经过时了,但是阅读问题和OP提供的答案似乎是 Maven 版本插件实际上可能是对他的问题的更好答案:
特别是可以使用以下目标:
- versions:use-latest-versions 在 pom 中搜索所有版本
这是较新的版本并且
将它们替换为最新的
版本。 - versions:use-latest-releases 在 pom 中搜索所有非 SNAPSHOT
较新的版本
释放并将它们替换为
最新发布版本。 - versions:update-properties 更新版本中定义的属性
项目,以便它们对应于
最新可用版本
特定的依赖关系。 这可以是
如果有一组依赖项,则很有用
必须全部锁定为一个版本。
还提供了以下其他目标:
- versions:display-dependency-updates 扫描项目的依赖项并
生成一份报告
具有更新的依赖项
可用版本。 - versions:display-plugin-updates 扫描项目的插件并
生成这些插件的报告
有更新的版本可用。 - versions:update-parent 更新项目的父部分,以便
它引用了最新的
可用版本。 例如,如果
你使用企业根 POM,这
如果您需要,目标可能会有所帮助
确保您使用的是最新的
公司根 POM 的版本。 - versions:update-child-modules 更新
项目的子模块,因此
版本与版本匹配
当前的项目。 例如,如果您
有一个聚合器 pom 也是
它的项目的父级
聚合体和子项以及
父版本不同步,这
mojo 可以帮助修复版本
子模块。 (请注意,您可能需要
使用 -N 选项调用 Maven
为了实现这个目标,如果你
项目被严重破坏了
由于版本原因无法构建
不匹配)。 - versions:lock-snapshots 在 pom 中搜索所有 -SNAPSHOT
版本并将其替换为
当前时间戳版本
-SNAPSHOT,例如 -20090327.172306-4 - versions:unlock-snapshots 在 pom 中搜索所有时间戳
锁定快照版本并替换
他们与-SNAPSHOT。 - versions:resolve-ranges 使用版本范围查找依赖项
将范围解析为特定的
正在使用的版本。 - versions:use-releases 在 pom 中搜索所有 -SNAPSHOT 版本
已发布并取代
他们与相应的版本
版本。 - versions:use-next-releases 在 pom 中搜索所有非 SNAPSHOT
较新的版本
释放并将它们替换为
下一个发行版本。 - versions:use-next-versions 搜索 pom 中的所有版本
这是较新的版本并且
将它们替换为下一个版本。 - versions:commit 删除 pom.xml.versionsBackup 文件。 形式
内置“穷人的”的一半
SCM”。 - versions:revert 从
pom.xml.versions备份文件。 形式
内置“穷人的”的一半
SCM”。
我只是想将其包含在内以供将来参考。
注意:
提到的LATEST
和RELEASE
元版本已在 Maven 3 中删除插件依赖项“为了可重现的构建”,6 年前。
(对于常规依赖关系,它们仍然可以完美地工作。)
有关插件依赖项,请参阅此Maven 3 兼容解决方案。
如果您始终想使用最新版本,Maven 有两个关键字可以用来替代版本范围。 您应该谨慎使用这些选项,因为您不再控制您正在使用的插件/依赖项。
当您依赖插件或依赖项时,可以使用 LATEST 或 RELEASE 的版本值。 LATEST 是指特定工件的最新发布版本或快照版本,即特定存储库中最近部署的工件。 RELEASE 指存储库中的最后一个非快照版本。 一般来说,设计依赖于工件的非特定版本的软件并不是最佳实践。 如果您正在开发软件,为了方便起见,您可能希望使用 RELEASE 或 LATEST,以便在发布新版本的第三方库时不必更新版本号。 当您发布软件时,您应该始终确保您的项目依赖于特定版本,以减少您的构建或项目受到不受您控制的软件版本影响的机会。 如果需要的话,请谨慎使用 LATEST 和 RELEASE。
请参阅 Maven 书籍的 POM 语法部分 了解更多详细信息。 或者参阅依赖版本范围上的文档,其中:
- 方括号 (
[
&]
) 表示“封闭”(包含)。 - 括号 (
(
&)
) 表示“开放”(独占)。
这是一个说明各种选项的示例。 在 Maven 存储库中,com.foo:my-foo 具有以下元数据:
<?xml version="1.0" encoding="UTF-8"?><metadata>
<groupId>com.foo</groupId>
<artifactId>my-foo</artifactId>
<version>2.0.0</version>
<versioning>
<release>1.1.1</release>
<versions>
<version>1.0</version>
<version>1.0.1</version>
<version>1.1</version>
<version>1.1.1</version>
<version>2.0.0</version>
</versions>
<lastUpdated>20090722140000</lastUpdated>
</versioning>
</metadata>
如果需要对该工件的依赖项,您有以下选项(其他 版本范围 当然可以指定,仅在此处显示相关的版本):
声明一个确切的版本(将始终解析为 1.0.1):
<version>[1.0.1]</version>
声明一个显式版本(除非发生冲突,否则将始终解析为 1.0.1,此时 Maven 将选择匹配的版本):
<version>1.0.1</version>
声明所有 1.x 的版本范围(当前将解析为 1.1。 1):
<version>[1.0.0,2.0.0)</version>
声明一个开放式版本范围(将解析为 2.0.0):
<version>[1.0.0,)</version>
将版本声明为 LATEST(将解析为 2.0.0)(从 maven 3.x 中删除)
<version>LATEST</version>
将版本声明为 RELEASE(将解析为 1.1) .1)(从maven 3.x中删除):
<version>RELEASE</version>
请注意,默认情况下,您自己的部署将更新Maven元数据中的“最新”条目,但要更新“发布”条目,您需要激活“发布配置文件”来自 Maven 超级 POM。 您可以使用“-Prelease-profile”或“-DperformRelease=true”来执行此操作
值得强调的是,任何允许 Maven 选择依赖项版本(LATEST、RELEASE 和版本范围)的方法都可能让您面临构建时间问题,因为更高版本可能有不同的行为(例如依赖插件之前已将默认值从 true 切换为 false,结果令人困惑)。
因此,在发行版中定义确切的版本通常是一个好主意。 作为 蒂姆的答案指出, maven-versions-plugin 是一个方便的工具用于更新依赖版本,特别是 versions:use-latest-版本 和 版本:use-latest-releases 目标。
如果你希望 Maven 使用最新版本的依赖项,那么你可以使用 Versions Maven Plugin以及如何使用这个插件,Tim已经给出了很好的答案,请按照他的答案进行操作。
但作为一名开发人员,我不会推荐这种做法。 为什么?
Pascal Thivent 在问题的评论中已经给出了原因的答案
我真的不推荐这种做法(也不使用版本范围)
为了构建的可重复性。 突然开始的构建
未知原因失败比手动更新更烦人
版本号。
我会推荐这种类型的做法:
<properties>
<spring.version>3.1.2.RELEASE</spring.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
</dependencies>
它易于维护且易于调试。 您可以立即更新您的 POM。
有时您不想使用版本范围,因为它们似乎解决您的依赖关系“缓慢”,特别是当持续交付到位并且有大量版本时 - 主要是在繁重的开发期间。
一种解决方法是使用 versions-maven-plugin。 例如,您可以声明一个属性:
<properties>
<myname.version>1.1.1</myname.version>
</properties>
并将 versions-maven-plugin 添加到您的 pom 文件中:
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>versions-maven-plugin</artifactId>
<version>2.3</version>
<configuration>
<properties>
<property>
<name>myname.version</name>
<dependencies>
<dependency>
<groupId>group-id</groupId>
<artifactId>artifact-id</artifactId>
<version>latest</version>
</dependency>
</dependencies>
</property>
</properties>
</configuration>
</plugin>
</plugins>
</build>
然后,为了更新依赖关系,您必须执行目标:
mvn versions:update-properties validate
如果有比 1.1.1 新的版本,则它会告诉你:
[INFO] Updated ${myname.version} from 1.1.1 to 1.3.2
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
提出这个问题时,maven 中的版本范围存在一些问题,但这些问题已在较新版本的 maven 中得到解决。
本文很好地描述了版本范围的工作原理以及最佳实践,以更好地理解 Maven 如何理解版本:https://docs.oracle.com/middleware/1212/core/MAVEN/maven_version.htm#MAVEN8855
By the time this question was posed there were some kinks with version ranges in maven, but these have been resolved in newer versions of maven.
This article captures very well how version ranges work and best practices to better understand how maven understands versions: https://docs.oracle.com/middleware/1212/core/MAVEN/maven_version.htm#MAVEN8855