855

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

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

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

4

12 回答 12

800

笔记:

6 多年前,“为了可重现的构建”,Maven 3 中的插件依赖项已经删除了上述LATESTRELEASE元版本。(对于常规依赖项,它们仍然可以正常工作。)对于插件依赖项,请参阅此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>

声明一个显式版本(将始终解析为 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 和版本范围)的方法都可能让您面临构建时间问题,因为更高版本可能有不同的行为(例如,依赖插件之前切换了默认值)值从真到假,结果令人困惑)。

因此,在发行版中定义确切的版本通常是一个好主意。正如蒂姆的回答所指出的,maven-versions-plugin是一个方便的工具,用于更新依赖版本,特别是版本:使用最新版本版本:使用最新版本目标。

于 2009-07-23T14:58:06.890 回答
413

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

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

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

还提供了以下其他目标:

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

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

于 2009-07-23T16:03:56.340 回答
173

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

<version>[1.2.3,)</version>

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

于 2008-08-27T16:56:03.053 回答
90

与其他人不同,我认为您可能总是想要最新版本的原因有很多。特别是如果您正在进行持续部署(我们有时一天会发布 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 版本插件快 100 倍。不幸的是,它不是以供公众使用的方式编写的,但是如果人们有兴趣,我可以这样做并将其放在 gist 或 github 中。

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

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

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

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

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

于 2012-01-09T21:21:59.943 回答
42

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

Dependenciesversion元素定义版本要求,用于计算有效的依赖版本。版本要求具有以下语法:

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

于 2015-07-22T16:21:29.223 回答
16

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

您可以只使用在必要时覆盖的快照版本,而不是增加开发版本的版本,这意味着您不必在每次微小更改时更改版本标签。1.0-SNAPSHOT 之类的东西...

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

于 2008-08-27T16:30:04.833 回答
10

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

mvn -U dependency:copy -Dartifact=com.foo:my-foo:LATEST
// pull the latest snapshot for my-foo from all repositories
于 2015-08-03T08:38:56.173 回答
7

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

于 2015-04-03T16:00:29.753 回答
7

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

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

所以结论是如果可以的话使用versions-maven-plugin 。

于 2015-06-26T15:53:25.037 回答
6

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

一种解决方法是使用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
于 2017-05-08T15:59:59.110 回答
4

如果您希望 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。

于 2018-04-18T09:10:06.463 回答
3

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

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

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

这个对我有用。

于 2018-10-07T03:52:05.730 回答