如何告诉Maven使用最新版本的依赖项?

在Maven中,依赖项通常是这样设置的:

<dependency><groupId>wonderful-inc</groupId><artifactId>dream-library</artifactId><version>1.2.3</version></dependency>

现在,如果你使用的是经常发布的库,不断更新标签可能有点烦人。有没有办法告诉Maven始终使用最新的可用版本(来自存储库)?

682114 次浏览

您是否可能依赖于在开发过程中明显变化很大的开发版本?

无需增加开发版本的版本,您可以只使用在必要时覆盖的快照版本,这意味着您不必在每次微小更改时更改版本标签。像1.0-SNAPSHOT…

但也许你正在努力实现其他目标;)

请查看此页面(“依赖版本范围”部分)。您可能想要做的是

<version>[1.2.3,)</version>

这些版本范围在Maven2中实现。

注:

6年前提到的LATESTRELEASE元版本在Maven 3中,为了可重现的构建而删除了插件依赖项。(它们仍然可以很好地用于常规依赖项。对于插件依赖项,请参考此符合Maven 3的解决方案


如果您总是想使用最新版本,Maven有两个关键字可以用作版本范围的替代。您应该小心使用这些选项,因为您不再控制您正在使用的插件/依赖项。

当您依赖于插件或依赖项时,您可以使用LATEST或RELEASE的a版本值。LATEST指的是特定工件的最新发布或快照版本,也就是特定存储库中最近部署的工件。RELEASE指的是存储库中最后一个非快照版本。通常,设计依赖于工件的非特定版本的软件不是最佳实践。如果您正在开发软件,您可能希望使用RELEASE或LATEST作为方便,这样当第三方库的新版本发布时,您就不必更新版本号。当您发布软件时,您应该始终确保您的项目依赖于特定的版本,以减少您的构建或您的项目受到不受您控制的软件版本影响的机会。

有关更多详细信息,请参阅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>

将版本声明为最新版本(将解析为2.0.0)(从maven 3. x中删除)

<version>LATEST</version>

将版本声明为RELEASE(将解析为1.1.1)(从maven 3. x中删除):

<version>RELEASE</version>

请注意,默认情况下,您自己的部署将更新Maven元数据中的“最新”条目,但要更新“发布”条目,您需要从Maven超级POM激活“释放配置文件”。您可以使用“-Prelees-file”或“-DperformRelease=true”执行此操作


值得强调的是,任何允许Maven选择依赖版本(LATEST,RELEASE和版本范围)的方法都可能导致构建时间问题,因为更高版本可能具有不同的行为(例如,依赖插件先前将默认值从true切换为false,结果令人困惑)。

因此,在发布中定义精确的版本通常是一个好主意。正如maven-版本-插件172805">蒂姆的回答指出的,maven-版本-插件是更新依赖版本的方便工具,特别是版本:使用-最新-版本版本:使用-最新-发布目标。

现在我知道这个话题已经过时了,但是阅读这个问题和OP提供的答案,似乎Maven版本插件实际上可能是他问题的更好答案:

特别是,以下目标可能有用:

  • 版本:使用-最新-版本在pom中搜索所有版本这是一个新的版本和用最新的替换它们版本。
  • 版本:使用-最新-发布在pom中搜索所有非SNAPSHOT更新的版本释放并用最新版本
  • 版本:更新-属性更新a中定义的属性项目,以便它们对应于最新可用版本的特定的依赖关系。这可能是如果一组依赖项有用必须全部锁定到一个版本。

还规定了以下其他目标:

  • 版本:显示-依赖-更新扫描项目的依赖关系编写一份关于这些具有较新可用的版本。
  • 版本:显示-插件-更新扫描项目的插件并生成这些插件的报告有更新的版本。
  • 版本:更新父更新项目的父部分,以便它引用了最新的可用版本。例如,如果您使用公司根POM,这目标可以帮助如果你需要确保您使用的是最新公司根POM的版本。
  • 版本:更新-子模块更新的父部分项目的子模块,因此版本匹配的版本当前项目。例如,如果您有一个聚合器pom,它也是它的项目的父级和儿童及父版本不同步,这Mojo可以帮助修复版本子模块。(注意您可能需要使用-N选项调用Maven为了运行这个目标,如果你项目被破坏得如此严重由于版本原因无法构建错误匹配)。
  • 版本:锁-快照在pom中搜索所有-SNAPSHOT版本并将它们替换为当前时间戳版本-SNAPSHOT,例如-20090327.172306-4
  • 版本:解锁-快照在pom中搜索所有时间戳锁定快照版本并替换使用-SNAPSHOT。
  • 版本:解决范围使用版本范围查找依赖项将范围解析为特定正在使用的版本。
  • 版本:使用-发布在pom中搜索所有-SNAPSHOT版本已经被释放并取代他们与相应的释放版本。
  • 版本:使用-下一个-发布在pom中搜索所有非SNAPSHOT更新的版本释放并用下一个版本。
  • 版本:使用-下一个-版本在pom中搜索所有版本这是一个新的版本和将它们替换为下一个版本。
  • 版本:提交删除pom.xml.versions备份文件内置“穷人”的一半SCM"。
  • 版本:恢复恢复pom.xml文件pom.xml.versions备份文件。表格内置“穷人”的一半SCM"。

我只是想把它包括在内,以备将来参考。

与其他人不同,我认为你可能会总是想要最新的版本有很多原因。特别是如果你正在进行持续部署(我们有时一天有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中引用的版本,它就无法更新到任何东西的最新版本。这实际上相当烦人,因为我们经常出于磁盘空间的原因清理旧版本。

实际上,你需要一个与maven分开的工具来调整版本(这样你就不会依赖pom文件来正确运行)。我用低级语言Bash编写了这样一个工具。该脚本将像版本插件一样更新版本,并将pom检查回源代码控制。它的运行速度也比mvn版本插件快100倍。不幸的是,它不是以公开使用的方式编写的,但如果人们感兴趣,我可以这样做,并将其放在gist或github中。

回到工作流程,因为一些评论询问这就是我们所做的:

  1. 我们有20个左右的项目在他们自己的仓库里有他们自己的Jenkins工作
  2. 当我们发布时使用maven发布插件。插件的留档中包含了该工作流程。maven发布插件有点糟糕(我很友好),但它确实有效。有一天我们计划用更优化的方法替换这种方法。
  3. 当其中一个项目发布jenkins然后运行一个特殊的作业时,我们将调用更新所有版本作业(jenkins如何知道它的发布是一个复杂的方式,部分原因是maven jenkins发布插件也很糟糕)。
  4. 更新所有版本作业知道所有20个项目。它实际上是一个聚合器pom,以依赖顺序指定模块部分中的所有项目。Jenkins运行我们的魔术groovy/bash foo,它将拉取所有项目更新到最新版本,然后签入pom(再次根据模块部分的依赖顺序完成)。
  5. 对于每个项目,如果pom发生了变化(因为某些依赖项中的版本更改),它会签入,然后我们立即ping jenkins为该项目运行相应的作业(这是为了保留构建依赖顺序,否则您将受到SCM Poll调度程序的支配)。

在这一点上,我认为无论如何,将发布和自动版本作为与您的常规构建分开的工具是一件好事。

现在,由于上面列出的问题,您可能会认为maven有点糟糕,但对于没有声明式易于解析可扩展语法(又名XML)的构建工具来说,这实际上是相当困难的。

事实上,我们通过命名空间添加自定义XML属性来帮助提示bash/groovy脚本(例如,不要更新此版本)。

在提出这个问题时,maven中的版本范围存在一些问题,但这些问题已在较新版本的maven中得到解决。本文很好地捕捉了版本范围的工作方式和最佳实践,以更好地理解maven如何理解版本:https://docs.oracle.com/middleware/1212/core/MAVEN/maven_version.htm#MAVEN8855

事实是即使在3. x中它仍然有效,令人惊讶的是项目构建和部署。但是LATEST/RELEASE关键字导致m2e和eclipse到处都是问题,此外,项目依赖于通过LATEST/RELEASE部署的依赖项无法识别版本。

如果您尝试将版本定义为属性,并在其他地方引用它,也会导致问题。

所以结论是如果可以的话,使用版本-maven-插件

依赖项语法位于依赖版本需求规范留档。这里是为了完整性:

依赖项的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(例如,如果已知不与此库结合使用)

在你的情况下,你可以做类似于<version>[1.2.3,)</version>的事情

谁在使用LATEST,请确保您有-U,否则不会提取最新的快照。

mvn -U dependency:copy -Dartifact=com.foo:my-foo:LATEST// pull the latest snapshot for my-foo from all repositories

有时您不想使用版本范围,因为它们似乎“缓慢”地解决您的依赖关系,特别是当持续交付并且有大量版本时-主要是在繁重的开发期间。

一种解决方法是使用版本-maven-插件。例如,您可以声明一个属性:

<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插件以及如何使用这个插件,Tim已经给出了很好的答案,按照他的回答

但作为开发人员,我不会推荐这种类型的做法。为什么?

为什么答案已经在问题的评论中由帕斯卡·蒂文特给出

我真的不推荐这种做法(也不使用版本范围)为了构建的可重复性。一个突然开始的构建未知原因失败比手动更新更烦人一个版本号。

我会推荐这种做法:

<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。

我在maven 3.5.4中的解决方案,使用nexus,在eclipse中:

<dependency><groupId>yilin.sheng</groupId><artifactId>webspherecore</artifactId><version>LATEST</version></dependency>

然后在eclipse中:atl + F5,选择force update of snapshots/release

它为我工作。