Java 如何告诉 Maven 使用最新版本的依赖项?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/30571/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do I tell Maven to use the latest version of a dependency?
提问by Anders Sandvig
In Maven, dependencies are usually set up like this:
在 Maven 中,依赖项通常是这样设置的:
<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)?
现在,如果您正在使用频繁发布的库,不断更新 <version> 标签可能会有些烦人。有什么方法可以告诉 Maven 始终使用最新的可用版本(来自存储库)?
采纳答案by Rich Seller
NOTE:
笔记:
This answer applies to Maven 2 only! The mentioned LATEST
and RELEASE
metaversions have been dropped in Maven 3 "for the sake of reproducible builds", over 6 years ago.
Please refer to this Maven 3 compliant solution.
此答案仅适用于 Maven 2!6 多年前,Maven 3“为了可重复的构建”已经删除了提到的LATEST
和RELEASE
元版本。请参阅此Maven 3 兼容解决方案。
If you always want to use the newest version, Maven has two keywords you can use as an alternative to version ranges. You should use these options with care as you are no longer in control of the plugins/dependencies you are using.
如果您总是想使用最新版本,Maven 有两个关键字可以用作版本范围的替代。您应该小心使用这些选项,因为您不再控制正在使用的插件/依赖项。
When you depend on a plugin or a dependency, you can use the a version value of LATEST or RELEASE. LATEST refers to the latest released or snapshot version of a particular artifact, the most recently deployed artifact in a particular repository. RELEASE refers to the last non-snapshot release in the repository. In general, it is not a best practice to design software which depends on a non-specific version of an artifact. If you are developing software, you might want to use RELEASE or LATEST as a convenience so that you don't have to update version numbers when a new release of a third-party library is released. When you release software, you should always make sure that your project depends on specific versions to reduce the chances of your build or your project being affected by a software release not under your control. Use LATEST and RELEASE with caution, if at all.
当您依赖某个插件或依赖项时,您可以使用 LATEST 或 RELEASE 的版本值。LATEST 是指特定工件的最新发布或快照版本,即特定存储库中最近部署的工件。RELEASE 是指存储库中的最后一个非快照版本。通常,设计依赖于工件的非特定版本的软件并不是最佳实践。如果您正在开发软件,您可能希望使用 RELEASE 或 LATEST 为方便起见,这样您就不必在发布第三方库的新版本时更新版本号。当您发布软件时,您应该始终确保您的项目依赖于特定版本,以减少您的构建或项目受到不受您控制的软件版本影响的可能性。
See the POM Syntax section of the Maven bookfor more details. Or see this doc on Dependency Version Ranges, where:
有关更多详细信息,请参阅Maven 书籍的POM 语法部分。或者在Dependency Version Ranges上查看此文档,其中:
- A square bracket (
[
&]
) means "closed" (inclusive). - A parenthesis (
(
&)
) means "open" (exclusive).
- 方括号 (
[
&]
) 表示“关闭”(包括)。 - 括号 (
(
&)
) 表示“开放”(独占)。
Here's an example illustrating the various options. In the Maven repository, com.foo:my-foo has the following metadata:
这是一个说明各种选项的示例。在 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>
If a dependency on that artifact is required, you have the following options (other version rangescan be specified of course, just showing the relevant ones here):
如果需要依赖于该工件,您有以下选项(当然可以指定其他版本范围,只在此处显示相关的):
Declare an exact version (will always resolve to 1.0.1):
声明一个确切的版本(将始终解析为 1.0.1):
<version>[1.0.1]</version>
Declare an explicit version (will always resolve to 1.0.1 unless a collision occurs, when Maven will select a matching version):
声明一个显式版本(除非发生冲突,否则将始终解析为 1.0.1,此时 Maven 将选择匹配的版本):
<version>1.0.1</version>
Declare a version range for all 1.x (will currently resolve to 1.1.1):
声明所有 1.x 的版本范围(目前将解析为 1.1.1):
<version>[1.0.0,2.0.0)</version>
Declare an open-ended version range (will resolve to 2.0.0):
声明一个开放式版本范围(将解析为 2.0.0):
<version>[1.0.0,)</version>
Declare the version as LATEST (will resolve to 2.0.0) (removed from maven 3.x)
将版本声明为 LATEST(将解析为 2.0.0)(从 maven 3.x 中删除)
<version>LATEST</version>
Declare the version as RELEASE (will resolve to 1.1.1) (removed from maven 3.x):
将版本声明为 RELEASE(将解析为 1.1.1)(从 maven 3.x 中删除):
<version>RELEASE</version>
Note that by default your own deployments will update the "latest" entry in the Maven metadata, but to update the "release" entry, you need to activate the "release-profile" from the Maven super POM. You can do this with either "-Prelease-profile" or "-DperformRelease=true"
请注意,默认情况下,您自己的部署将更新 Maven 元数据中的“最新”条目,但要更新“发布”条目,您需要从Maven 超级 POM激活“发布配置文件” 。您可以使用“-Prelease-profile”或“-DperformRelease=true”来执行此操作
It's worth emphasising that any approach that allows Maven to pick the dependency versions (LATEST, RELEASE, and version ranges) can leave you open to build time issues, as later versions can have different behaviour (for example the dependency plugin has previously switched a default value from true to false, with confusing results).
值得强调的是,任何允许 Maven 选择依赖版本(LATEST、RELEASE 和版本范围)的方法都可以让您对构建时间问题持开放态度,因为以后的版本可能有不同的行为(例如,依赖插件以前切换了默认值)值从真到假,结果令人困惑)。
It is therefore generally a good idea to define exact versions in releases. As Tim's answerpoints out, the maven-versions-pluginis a handy tool for updating dependency versions, particularly the versions:use-latest-versionsand versions:use-latest-releasesgoals.
因此,在发行版中定义确切的版本通常是一个好主意。正如Tim 的回答所指出的,maven-versions-plugin是一个用于更新依赖项版本的便捷工具,尤其是versions:use-latest-versions和versions:use-latest-releases目标。
回答by Martin Klinke
Are you possibly depending on development versions that obviously change a lot during development?
您是否可能依赖在开发过程中明显变化很大的开发版本?
Instead of incrementing the version of development releases, you could just use a snapshot version that you overwrite when necessary, which means you wouldn't have to change the version tag on every minor change. Something like 1.0-SNAPSHOT...
您可以只使用在必要时覆盖的快照版本,而不是增加开发版本的版本,这意味着您不必在每次细微更改时更改版本标记。像 1.0-SNAPSHOT 之类的东西...
But maybe you are trying to achieve something else ;)
但也许你正在努力实现其他目标 ;)
回答by Martin Klinke
回答by Tim
Now I know this topic is old, but reading the question and the OP supplied answer it seems the Maven Versions Pluginmight have actually been a better answer to his question:
现在我知道这个话题已经过时了,但是阅读问题和 OP 提供的答案似乎Maven 版本插件实际上可能是他问题的更好答案:
In particular the following goals could be of use:
特别是以下目标可能有用:
- versions:use-latest-versionssearches the pom for all versions which have been a newer version and replaces them with the latest version.
- versions:use-latest-releasessearches the pom for all non-SNAPSHOT versions which have been a newer release and replaces them with the latest release version.
- versions:update-propertiesupdates properties defined in a project so that they correspond to the latest available version of specific dependencies. This can be useful if a suite of dependencies must all be locked to one version.
- 版本:use-latest-versions在 pom 中搜索所有较新版本的版本,并将它们替换为最新版本。
- 版本:use-latest-releases在 pom 中搜索所有非 SNAPSHOT 版本的较新版本,并将它们替换为最新版本。
- version:update-properties更新项目中定义的属性,以便它们对应于特定依赖项的最新可用版本。如果必须将一组依赖项全部锁定到一个版本,这会很有用。
The following other goals are also provided:
还提供了以下其他目标:
- versions:display-dependency-updatesscans a project's dependencies and produces a report of those dependencies which have newer versions available.
- versions:display-plugin-updatesscans a project's plugins and produces a report of those plugins which have newer versions available.
- versions:update-parentupdates the parent section of a project so that it references the newest available version. For example, if you use a corporate root POM, this goal can be helpful if you need to ensure you are using the latest version of the corporate root POM.
- versions:update-child-modulesupdates the parent section of the child modules of a project so the version matches the version of the current project. For example, if you have an aggregator pom that is also the parent for the projects that it aggregates and the children and parent versions get out of sync, this mojo can help fix the versions of the child modules. (Note you may need to invoke Maven with the -N option in order to run this goal if your project is broken so badly that it cannot build because of the version mis-match).
- versions:lock-snapshotssearches the pom for all -SNAPSHOT versions and replaces them with the current timestamp version of that -SNAPSHOT, e.g. -20090327.172306-4
- versions:unlock-snapshotssearches the pom for all timestamp locked snapshot versions and replaces them with -SNAPSHOT.
- versions:resolve-rangesfinds dependencies using version ranges and resolves the range to the specific version being used.
- versions:use-releasessearches the pom for all -SNAPSHOT versions which have been released and replaces them with the corresponding release version.
- versions:use-next-releasessearches the pom for all non-SNAPSHOT versions which have been a newer release and replaces them with the next release version.
- versions:use-next-versionssearches the pom for all versions which have been a newer version and replaces them with the next version.
- versions:commitremoves the pom.xml.versionsBackup files. Forms one half of the built-in "Poor Man's SCM".
- versions:revertrestores the pom.xml files from the pom.xml.versionsBackup files. Forms one half of the built-in "Poor Man's SCM".
- 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”的一半。
Just thought I'd include it for any future reference.
只是想我会把它包括在内以供将来参考。
回答by Adam Gent
Unlike others I think there are many reasons why you might always want the latestversion. Particularly if you are doing continuous deployment (we sometimes have like 5 releases in a day) and don't want to do a multi-module project.
与其他人不同,我认为您可能总是想要最新版本的原因有很多。特别是如果你正在进行持续部署(我们有时一天有 5 个版本)并且不想做一个多模块项目。
What I do is make Hudson/Jenkins do the following for every build:
我所做的是让 Hudson/Jenkins 为每个构建执行以下操作:
mvn clean versions:use-latest-versions scm:checkin deploy -Dmessage="update versions" -DperformRelease=true
That is I use the versions plugin and scm plugin to update the dependencies and then check it in to source control. Yes I let my CI do SCM checkins (which you have to do anyway for the maven release plugin).
那就是我使用版本插件和 scm 插件来更新依赖项,然后将其签入源代码管理。是的,我让我的 CI 进行 SCM 签入(无论如何您必须为 maven 发布插件执行此操作)。
You'll want to setup the versions plugin to only update what you want:
您需要设置版本插件以仅更新您想要的内容:
<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>
I use the release plugin to do the release which takes care of -SNAPSHOT and validates that there is a release version of -SNAPSHOT (which is important).
我使用发布插件来执行发布,它负责处理 -SNAPSHOT 并验证是否存在 -SNAPSHOT 的发布版本(这很重要)。
If you do what I do you will get the latest version for all snapshot builds and the latest release version for release builds. Your builds will also be reproducible.
如果您按照我的操作进行操作,您将获得所有快照构建的最新版本和发布构建的最新发布版本。您的构建也将是可复制的。
Update
更新
I noticed some comments asking some specifics of this workflow. I will say we don't use this method anymore and the big reason why is the maven versions plugin is buggy and in general is inherently flawed.
我注意到一些评论询问了这个工作流程的一些细节。我会说我们不再使用这种方法了,一个重要的原因是 maven 版本插件是有缺陷的,并且通常存在固有的缺陷。
It is flawed because to run the versions plugin to adjust versions all the existing versions need to exist for the pom to run correctly. That is the versions plugin cannot update to the latest version of anything if it can't find the version referenced in the pom. This is actually rather annoying as we often cleanup old versions for disk space reasons.
这是有缺陷的,因为要运行版本插件来调整版本,所有现有版本都需要存在才能使 pom 正确运行。也就是说,如果在 pom.xml 文件中找不到引用的版本,则版本插件无法更新到任何内容的最新版本。这实际上很烦人,因为我们经常出于磁盘空间的原因清理旧版本。
Really you need a separate tool from maven to adjust the versions (so you don't depend on the pom file to run correctly). I have written such a tool in the the lowly language that is Bash. The script will update the versions like the version plugin and check the pom back into source control. It also runs like 100x faster than the mvn versions plugin. Unfortunately it isn't written in a manner for public usage but if people are interested I could make it so and put it in a gist or github.
确实,您需要一个来自 maven 的单独工具来调整版本(因此您不依赖于 pom 文件才能正确运行)。我已经用 Bash 的低级语言编写了这样一个工具。该脚本将像版本插件一样更新版本并将 pom 检回源代码控制。它的运行速度也比 mvn 版本插件快 100 倍。不幸的是,它不是以供公众使用的方式编写的,但如果人们感兴趣,我可以这样做并将其放在要点或 github 中。
Going back to workflow as some comments asked about that this is what we do:
回到工作流程,因为一些评论询问我们这就是我们所做的:
- We have 20 or so projects in their own repositories with their own jenkins jobs
- When we release the maven release plugin is used. The workflow of that is covered in the plugin's documentation. The maven release plugin sort of sucks (and I'm being kind) but it does work. One day we plan on replacing this method with something more optimal.
- When one of the projects gets released jenkins then runs a special job we will call the update all versions job (how jenkins knows its a release is a complicated manner in part because the maven jenkins release plugin is pretty crappy as well).
- The update all versions job knows about all the 20 projects. It is actually an aggregator pom to be specific with all the projects in the modules section in dependency order. Jenkins runs our magic groovy/bash foo that will pull all the projects update the versions to the latest and then checkin the poms (again done in dependency order based on the modules section).
- For each project if the pom has changed (because of a version change in some dependency) it is checked in and then we immediately ping jenkins to run the corresponding job for that project (this is to preserve build dependency order otherwise you are at the mercy of the SCM Poll scheduler).
- 我们在他们自己的存储库中有 20 个左右的项目,他们有自己的 jenkins 工作
- 当我们发布时使用了 maven 发布插件。插件的文档中介绍了该工作流程。maven 发布插件有点糟糕(我很善良)但它确实有效。有一天,我们计划用更优化的方法替换这种方法。
- 当其中一个项目发布时,jenkins 运行一项特殊作业,我们将调用更新所有版本作业(jenkins 如何知道它的发布是一种复杂的方式,部分原因是 maven jenkins 发布插件也非常糟糕)。
- 更新所有版本作业了解所有 20 个项目。它实际上是一个聚合器 pom,以依赖顺序特定于模块部分中的所有项目。Jenkins 运行我们的魔法 groovy/bash foo,它将把所有项目更新到最新版本,然后签入 poms(再次根据模块部分的依赖顺序完成)。
- 对于每个项目,如果 pom 已更改(由于某些依赖项中的版本更改),则将其签入,然后我们立即 ping jenkins 以运行该项目的相应作业(这是为了保留构建依赖项顺序,否则您将受到摆布SCM 轮询调度程序)。
At this point I'm of the opinion it is a good thing to have the release and auto version a separate tool from your general build anyway.
在这一点上,我认为无论如何将发布和自动版本作为与常规构建分开的工具是一件好事。
Now you might think maven sort of sucks because of the problems listed above but this actually would be fairly difficult with a build tool that does not have a declarative easy to parse extendablesyntax (aka XML).
现在您可能认为 maven 有点糟糕,因为上面列出的问题,但是对于没有声明性易于解析的可扩展语法(又名 XML)的构建工具,这实际上是相当困难的。
In fact we add custom XML attributes through namespaces to help hint bash/groovy scripts (e.g. don't update this version).
事实上,我们通过命名空间添加自定义 XML 属性来帮助提示 bash/groovy 脚本(例如,不要更新此版本)。
回答by bclarance
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
在提出这个问题时,maven 中的版本范围存在一些问题,但这些问题已在较新版本的 maven 中得到解决。本文很好地捕捉了版本范围的工作原理和最佳实践,以更好地理解 maven 如何理解版本:https: //docs.oracle.com/middleware/1212/core/MAVEN/maven_version.htm#MAVEN8855
回答by Junchen Liu
The truth is even in 3.x it still works, surprisingly the projects builds and deploys. But the LATEST/RELEASE keyword causing problems in m2e and eclipse all over the place, ALSO projects depends on the dependency which deployed through the LATEST/RELEASE fail to recognize the version.
事实是即使在 3.x 中它仍然有效,令人惊讶的是项目构建和部署。但是 LATEST/RELEASE 关键字导致 m2e 和 eclipse 到处出现问题,ALSO 项目依赖于通过 LATEST/RELEASE 部署的依赖项无法识别版本。
It will also causing problem if you are try to define the version as property, and reference it else where.
如果您尝试将版本定义为属性,并在其他地方引用它,它也会导致问题。
So the conclusion is use the versions-maven-pluginif you can.
所以结论是如果可以的话,使用versions-maven-plugin。
回答by mkobit
The dependencies syntax is located at the Dependency Version Requirement Specificationdocumentation. Here it is is for completeness:
依赖项语法位于依赖项版本要求规范文档中。这是为了完整性:
Dependencies'
version
element define version requirements, used to compute effective dependency version. Version requirements have the following syntax:
1.0
: "Soft" requirement on 1.0 (just a recommendation, if it matches all other ranges for the dependency)[1.0]
: "Hard" requirement on 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 or x >= 1.2; multiple sets are comma-separated(,1.1),(1.1,)
: this excludes 1.1 (for example if it is known not to work in combination with this library)
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(例如,如果已知不能与此库结合使用)
In your case, you could do something like <version>[1.2.3,)</version>
在你的情况下,你可以做类似的事情 <version>[1.2.3,)</version>
回答by trung
Who ever is using LATEST, please make sure you have -U otherwise the latest snapshot won't be pulled.
谁在使用 LATEST,请确保您有 -U 否则不会拉取最新的快照。
mvn -U dependency:copy -Dartifact=com.foo:my-foo:LATEST
// pull the latest snapshot for my-foo from all repositories
回答by Markon
Sometimes you don't want to use version ranges, because it seems that they are "slow" to resolve your dependencies, especially when there is continuous delivery in place and there are tons of versions - mainly during heavy development.
有时您不想使用版本范围,因为它们似乎“缓慢”解决您的依赖项,尤其是在持续交付到位并且有大量版本时 - 主要是在繁重的开发期间。
One workaround would be to use the versions-maven-plugin. For example, you can declare a property:
一种解决方法是使用versions-maven-plugin。例如,您可以声明一个属性:
<properties>
<myname.version>1.1.1</myname.version>
</properties>
and add the versions-maven-plugin to your pom file:
并将 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>
Then, in order to update the dependency, you have to execute the goals:
然后,为了更新依赖项,您必须执行目标:
mvn versions:update-properties validate
If there is a version newer than 1.1.1, it will tell you:
如果有比 1.1.1 更新的版本,它会告诉你:
[INFO] Updated ${myname.version} from 1.1.1 to 1.3.2