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


788

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

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

现在,如果您正在使用发布频繁的库,则不断更新<version>标记可能会有些烦人。有什么方法可以告诉Maven始终使用最新版本(来自存储库)?


@Martin我知道xyz-SNAPSHOT约定,但是我正在考虑以最终版本发布到存储库的库(即,从dream-library-1.2.3.jar到dream-library-1.2.4.jar , 等等)。
Anders Sandvig

176
我真的不建议这种做法(也不要使用版本范围),以确保生成的可重复性。由于未知原因开始突然失败的构建比手动更新版本号更令人讨厌。
Pascal Thivent 09年

12
@PascalThivent如果要进行连续发行,则手动更新pom中的发行号是一件很麻烦的事情。我将版本插件与scm插件结合使用来解决这个问题(请参阅我的答案)。
亚当·根特

4
@PascalThivent两者都很烦人,但是方式不同。我想根据自己的情况在两者之间进行选择,而不要被迫使用,因为其他人认为这会更好。
piegames

Answers:


744

注意:

此答案仅适用于Maven 2!在6年前,“出于可复制的构建”而已在Maven 3中删除了提到的LATESTRELEASEmetaversions 。请参考此兼容Maven 3的解决方案


如果您始终想使用最新版本,则Maven有两个关键字可以用作版本范围的替代。您应该谨慎使用这些选项,因为您将不再控制所使用的插件/依赖项。

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

有关更多详细信息,请参见Maven书籍POM语法部分。或者在Dependency Version Ranges上查看此文档,其中:

  • 方括号([])表示“封闭”(含)。
  • 括号(())表示“开放”(不包括在内)。

这是说明各种选项的示例。在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>

声明一个明确的版本(除非发生冲突,否则当Maven选择一个匹配的版本时,它将始终解析为1.0.1):

<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激活“发布配置文件” 。您可以使用“ -Prelease-profile”或“ -DperformRelease = true”来执行此操作


值得强调的是,任何允许Maven选择依赖版本(最新,发布和版本范围)的方法都可以让您开放以解决时间问题,因为更高版本的行为可能不同(例如,依赖插件先前已将默认设置切换为默认值)。值从true到false,结果令人困惑)。

因此,通常最好在发行版中定义确切的版本。正如Tim的答案所指出的那样,maven-versions-plugin是用于更新依赖项版本的便捷工具,尤其是版本:use-latest-versions版本:use-latest-releases目标。


76
嗨,Rich!看来Maven 3.x不再支持 RELEASE和LATEST版本标记。
Pascal Thivent

16
如果我正确理解文档,那么该弃用似乎仅适用于插件,而不适用于常规依赖关系
Mond Raymond

9
@RichSeller嘿,里奇;我花了一些时间,然后才发现Maven 3.0中不再可用;)您是否考虑编辑答案,以便从说明Maven 3.0弃用的更新开始?谢谢一群!
Miquel

6
我相信一个不错的平衡是锁定主要版本,但获得最新的次要(或补丁)版本(无论哪种版本,仅在您所依赖的artifcat中用于错误修复)。使用当前语法,这似乎仅在以下范围内才有可能(注意:以方括号开头,以括号结尾):[1.1,2.0)
Amr Mostafa 2014年

2
FWIW ...更新链接Maven3兼容性说明:cwiki.apache.org/confluence/display/MAVEN/...
dyodji

383

现在我知道这个主题很老,但是阅读问题和OP提供的答案后,似乎Maven Versions插件实际上可能是他的问题的更好答案:

特别是可以使用以下目标:

  • 版本:use-latest-versions在pom中搜索所有已为较新版本的版本,并将其替换为最新版本。
  • 版本:use-latest-releases在pom中搜索所有非SNAPSHOT版本,这些版本都是较新的版本,并将其替换为最新版本。
  • 版本:update-properties更新项目中定义的属性,以便它们与特定依赖项的最新可用版本相对应。如果必须将所有依赖项套件都锁定到一个版本,这将很有用。

还提供了以下其他目标:

  • 版本:display-dependency-updates扫描项目的依赖关系,并生成这些依赖关系的报告,这些报告具有较新的版本。
  • 版本:display-plugin-updates扫描项目的插件,并生成这些插件具有较新版本的报告。
  • 版本:update-parent更新项目的上级部分,以便它引用最新的可用版本。例如,如果您使用公司根POM,则在需要确保使用最新版本的公司根POM时,此目标可能会有所帮助。
  • 版本:update-child-modules更新项目子模块的父部分,因此版本与当前项目的版本匹配。例如,如果您有一个聚合器pom也是它聚合的项目的父级,而子级和父级版本不同步,则此mojo可以帮助修复子级模块的版本。(请注意,如果您的项目被严重破坏以至于由于版本不匹配而无法构建,则可能需要使用-N选项调用Maven才能运行此目标)。
  • 版本:lock-snapshots在pom中搜索所有-SNAPSHOT版本,并将其替换为该-SNAPSHOT的当前时间戳版本,例如-20090327.172306-4
  • 版本:unlock-snapshots在pom中搜索所有时间戳锁定的快照版本,并将其替换为-SNAPSHOT。
  • 版本:resolve-ranges使用版本范围查找依赖项,并将范围解析为所使用的特定版本。
  • 版本:use-releases在pom中搜索所有已发布的-SNAPSHOT版本,并将其替换为相应的发布版本。
  • 版本:use-next-releases在pom中搜索所有非SNAPSHOT版本,这些版本已经是较新的发行版,并将其替换为下一发行版。
  • 版本:use-next-versions在pom中搜索所有已为较新版本的版本,并将其替换为下一个版本。
  • 版本:commit删除pom.xml.versionsBackup文件。构成内置的“穷人SCM”的一半。
  • 版本:还原从pom.xml.versionsBackup文件中还原pom.xml文件。构成内置的“穷人SCM”的一半。

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


10
在这种情况下,“发行版”和“版本”之间有什么区别?
本·诺兰德

1
@BenNoland,我相信在这种情况下的区别是,下一版本可能不需要是发布工件。例如,给定一个版本为1.0.0-SNAPSHOT,1.0.0和1.0.1-SNAPSHOT的工件,以及对1.0.0-SNAPSHOT的pom引用,version:next-versions和versions:next-releases将解析为1.0.0。 ,而版本:最新版本和版本:最新版本将分别解析为1.0.1-SNAPSHOT和1.0.0。
Ryan Beesley 2014年

1
您可以在此非常好的表格中解决版本/发行版/快照之间的一些不确定性:goo.gl/iDq6PK
Ev0oD 2014年

1
打印所有可能且不相关的目标无济于事。
MariuszS 2015年

2
我认为version:use-latest-versions解决了大多数OP的问题。
亚历克斯R

172

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

<version>[1.2.3,)</version>

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


由于某种原因,该选项对我不起作用,它选择了范围内的版本,但不是最新版本。
sorin 2012年

4
您可能希望更仔细地了解Maven如何比较版本号-如果您不遵循严格的模式,Maven会将其比较为字符串而不是数字。
托尔比约恩Ravn的安德森

该页面位于Codehaus上,并将其自身描述为“尚未为Maven 2.0实施的东西”。Maven文档本身未提及任何有关版本范围的信息。我想念什么吗?什么时候引入版本范围?官方文档在哪里描述了它们?
香农

1
您错了,版本范围意味着从1.2.3到更高版本的所有版本都是可以的。这根本不是最新版本。
MariuszS

@sorin您的项目中是否还有其他依赖项,这些依赖项也取决于所讨论的工件?尝试mvn dependency:tree -Dverbose找出答案。这可以解释意外的版本。
尤金·别列索夫斯基

83

与其他人不同,我认为有很多原因可能导致您始终需要最新版本。特别是如果您要进行连续部署(有时一天会有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倍。不幸的是,它不是以供公众使用的方式编写的,但是如果人们感兴趣,我可以这样做,然后将其放入要点或github中。

回到工作流程,一些评论询问我们正在做什么:

  1. 我们在自己的存储库中有20个左右的项目,拥有自己的詹金斯工作
  2. 当我们发布Maven发布插件时。插件的文档中涵盖了工作流程。Maven发行插件有点糟透了(我很客气),但确实可以。有一天,我们计划用更优化的方法代替这种方法。
  3. 当其中一个项目被发布时,jenkins然后运行一项特殊的工作,我们将称为更新所有版本的工作(jenkins知道其发布是一种复杂的方式,部分原因是maven jenkins release插件也很糟糕)。
  4. “更新所有版本”作业了解所有20个项目。实际上,它是一个聚合器pom,它以依赖关系的顺序特定于模块部分中的所有项目。詹金斯(Jenkins)运行我们的魔术groovy / bash foo,它将把所有项目更新为最新版本,然后检入poms(再次根据模块部分以依赖顺序完成)。
  5. 对于每个项目,如果pom发生了更改(由于某些依赖项的版本更改),则将其签入,然后我们立即ping jenkins来为该项目运行相应的工作(这是为了保留构建依赖项的顺序,否则您将大为屈服SCM轮询调度程序)。

在这一点上,我认为将发布和自动版本与您的常规版本分开使用是一个不错的选择。

现在您可能会因为上面列出的问题而认为行家有点烂,但是使用没有声明性的易于解析可扩展语法(又称XML)的构建工具,这实际上会很困难。

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


5
感谢您在回答中包含动机(持续部署)。
David J. Liszewski 2012年

10
我认为使用此方法可重现构建的要点,而在使用版本范围或-LATEST时,则不是!
marc.guenther

我想在运行构建之前使用外部工具更改项目pom的第二个解决方案。我们也使用这种方法,因为版本范围插件本身就是错误的,例如考虑日期而不是仅考虑版本。
Daniel Hajduk

37

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

依赖项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>


15

您是否可能依赖于开发版本,这些版本在开发期间显然会发生很大变化?

除了增加开发版本的版本外,您还可以使用在必要时覆盖的快照版本,这意味着您不必在每次更改时都更改版本标签。像1.0-快照...

但是也许您正在尝试实现其他目标;)


7

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

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

甚至使用-UI都得到了Couldn't download artifact: Failed to resolve version for com.app:common:jar:LATEST
罗伯特·罗伯特(Robert)


6

事实是,即使在3.x中它仍然可以工作,令人惊讶的是,这些项目可以构建和部署。但是LATEST / RELEASE关键字在m2e中引起问题,并使整个地方都黯然失色,ALSO项目依赖于通过LATEST / RELEASE部署的依赖项无法识别版本。

如果尝试将版本定义为属性,并在其他位置引用它,也会引起问题。

因此,结论是,如果可以,请使用versions-maven-plugin


5

有时您不希望使用版本范围,因为它们似乎很“缓慢”地解决了您的依赖性,尤其是在持续交付且有大量版本的情况下-主要是在繁重的开发过程中。

一种解决方法是使用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

3

如果您希望Maven使用最新版本的依赖项,则可以使用Versions Maven插件以及如何使用此插件,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,则该构建仍可重现。更新Maven版本可以在一个单独的提交中完成(正如您从我的回答中看到的那样,您必须指定一个单独的目标,但这在构建中并没有神奇地发生)。
Markon

1

我在Maven 3.5.4中的解决方案,在月食中使用nexus:

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

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

这个对我有用。


尽管出于各种原因在上面已经明确指出了原因,但是在命令行上无法工作。我们中的许多人必须遵循自动化构建,因此我们的POM必须在命令行运行时才能工作,而不仅仅是在Eclipse中运行。
bigbadmouse18年

我正在使用maven 3.5.4,并在使用“最新”时得到了这个信息:是LATEST还是RELEASE(都已弃用)@第154行第13列
Leonardo Leonardo
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.