繁体   English   中英

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

[英]How do I tell Maven to use the latest version of a dependency?

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

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

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

笔记:

提到的LATESTRELEASE metaversions 已经在 Maven 3 中“为了可重复的构建”中的插件依赖项被删除,6 多年前。 (对于常规依赖项,它们仍然可以正常工作。)对于插件依赖项,请参阅此Maven 3 兼容解决方案


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

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

有关更多详细信息,请参阅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 和版本范围)的方法都可以让您对构建时间问题持开放态度,因为以后的版本可能有不同的行为(例如,依赖插件以前切换了默认值)值从真到假,结果令人困惑)。

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

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

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

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

还提供了以下其他目标:

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

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

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

<version>[1.2.3,)</version>

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

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

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

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

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

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

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

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

Dependencies 的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>

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

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

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

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

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

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

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

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

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

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

一种解决方法是使用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 应该使用最新版本的依赖项,那么你可以使用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。

我在 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/releaseforce update of snapshots/release

这个对我有用。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM