论坛
不知道 maven 的这个特性,你迟早要被坑
引用于 程序员子悠 在 2024年2月14日, 下午2:50
Apache Maven
是一个自动化构建工具,广泛应用于Java
项目,它可以帮助我们管理项目的构建、报告和文档,但最重要的功能之一是依赖管理。只要正确配置了项目的依赖,
Maven
在编译的时候就可以自动下载项目所需的所有依赖项。但是如果我们使用不当,依赖管理可能会引入问题,特别是当我们使用如[2.3.0,)
这样的版本范围指定的时候。这样的写法意味着依赖的版本要大于等于
2.3.0
,但不指定最大版本,maven
在编译的时候会自动去查询当前最新的版本,这就很大程度上可能会引入了最新的版本,导致项目依赖不固定,从而引发编译异常。Maven 版本范围介绍
在
Maven
的依赖管理中,我们可以为依赖项指定一个版本范围。例如,[1.0,2.0]
意味着版本范围介于1.0
和2.0
之间(包含)。[1.0,2.0)
意味着版本范围介于1.0
和2.0
之间,但不包含2.0
。[2.3.0,)
则表明我们接受2.3.0
或更高的版本,此时我们并没有指定范围的上限,而是让Maven
选择满足这个条件的最新版本。版本范围带来的问题
对于某些类型的项目,如开源项目,使用范围可能是合理的,因为开源项目通常希望能够方便地采用最新的库和工具。
然而,对于需要保证稳定性的商业项目,使用无上限的版本范围可能导致问题。每次构建项目时,
Maven
都会尝试获取新的依赖版本。如果新版本引入了不兼容的更改,可能导致编译错误,甚至更微妙的运行时错误。由于同一项目的不同开发者可能在不同的时间点执行编译,他们可能获得的依赖版本不同,从而导致难以追踪的问题。
而作为公司内部的软件,很多时候我们是需要保证稳定的,所以就很不适合采用范围来配置
maven
版本了。如下所示,我这边原本的配置
fastjson
的版本是1.2.79
,从右侧的maven
依赖中我们可以看到,项目中下载的fastjson
的版本是1.2.79
。如果此时我把
fastjson
的版本调整成[1.2.79,)
的形式,则右侧的依赖就会变成一个最新的2.0.45
这个版本。这种写法除了依赖中会获取到最新的版本之外,其实
maven
是把整个范围的jar
都下载下来了,通过本地的资源仓库我们可以看到只要版本在这个范围之内,都会被下载下来。另外如果一些软件自身的升级是向下兼容的,那么使用范围版本配置可能没什么关系,但是如果一些软件的版本不是向下兼容的,那么使用范围版本配置那肯定是有问题的。
特别是随着
JDK
版本的升级,很多新的依赖的开发和编译可能是采用新版本的JDK
来实现的,这个时候如果我们自身项目的JDK
还是旧版本的话,就会出现项目编译不通过的问题了,会提示JDK
版本不对,这种在编译的时候往往会出现Java – Unsupported class file major version
异常。所以下次如果出现这种异常,可以考虑看看是不是
maven
版本依赖配置问题。如何解决明确版本问题
最简单和最直接的方法是将依赖的版本明确指定,而不是提供一个范围。
这样,所有开发者和构建服务器都将使用相同的依赖版本。当我们决定升级依赖时,可以测试新版本,对代码进行必要的更改,然后在进行升级。
Maven
也支持所谓的版本管理(version management)
。在父POM
中,我们可以用<dependencyManagement>
元素定义一个或多个依赖项的版本,然后在项目的各个模块中引用它们,无需在每个模块中指定版本。这种方法对于确保项目的各个部分使用相同的依赖版本非常有效。结论
虽然范围版本提供了寻找需要的库的新版本的方便,但大范围的未定版本和更新可能会引入不希望的结果,这些结果可能导致编译异常或者运行时错误。
我们需要使用正确的方法来管理和锁定我们的依赖,避免这些困扰,并保持我们的项目的稳定性。
Apache Maven
是一个自动化构建工具,广泛应用于 Java
项目,它可以帮助我们管理项目的构建、报告和文档,但最重要的功能之一是依赖管理。
只要正确配置了项目的依赖,Maven
在编译的时候就可以自动下载项目所需的所有依赖项。但是如果我们使用不当,依赖管理可能会引入问题,特别是当我们使用如 [2.3.0,)
这样的版本范围指定的时候。
这样的写法意味着依赖的版本要大于等于 2.3.0
,但不指定最大版本,maven
在编译的时候会自动去查询当前最新的版本,这就很大程度上可能会引入了最新的版本,导致项目依赖不固定,从而引发编译异常。
Maven 版本范围介绍
在 Maven
的依赖管理中,我们可以为依赖项指定一个版本范围。例如,[1.0,2.0]
意味着版本范围介于 1.0
和 2.0
之间(包含)。[1.0,2.0)
意味着版本范围介于 1.0
和 2.0
之间,但不包含 2.0
。[2.3.0,)
则表明我们接受 2.3.0
或更高的版本,此时我们并没有指定范围的上限,而是让 Maven
选择满足这个条件的最新版本。
版本范围带来的问题
对于某些类型的项目,如开源项目,使用范围可能是合理的,因为开源项目通常希望能够方便地采用最新的库和工具。
然而,对于需要保证稳定性的商业项目,使用无上限的版本范围可能导致问题。每次构建项目时,Maven
都会尝试获取新的依赖版本。如果新版本引入了不兼容的更改,可能导致编译错误,甚至更微妙的运行时错误。
由于同一项目的不同开发者可能在不同的时间点执行编译,他们可能获得的依赖版本不同,从而导致难以追踪的问题。
而作为公司内部的软件,很多时候我们是需要保证稳定的,所以就很不适合采用范围来配置 maven
版本了。
如下所示,我这边原本的配置 fastjson
的版本是 1.2.79
,从右侧的 maven
依赖中我们可以看到,项目中下载的 fastjson
的版本是 1.2.79
。
如果此时我把 fastjson
的版本调整成 [1.2.79,)
的形式,则右侧的依赖就会变成一个最新的 2.0.45
这个版本。
这种写法除了依赖中会获取到最新的版本之外,其实 maven
是把整个范围的 jar
都下载下来了,通过本地的资源仓库我们可以看到只要版本在这个范围之内,都会被下载下来。
另外如果一些软件自身的升级是向下兼容的,那么使用范围版本配置可能没什么关系,但是如果一些软件的版本不是向下兼容的,那么使用范围版本配置那肯定是有问题的。
特别是随着 JDK
版本的升级,很多新的依赖的开发和编译可能是采用新版本的 JDK
来实现的,这个时候如果我们自身项目的 JDK
还是旧版本的话,就会出现项目编译不通过的问题了,会提示 JDK
版本不对,这种在编译的时候往往会出现 Java – Unsupported class file major version
异常。
所以下次如果出现这种异常,可以考虑看看是不是 maven
版本依赖配置问题。
如何解决明确版本问题
最简单和最直接的方法是将依赖的版本明确指定,而不是提供一个范围。
这样,所有开发者和构建服务器都将使用相同的依赖版本。当我们决定升级依赖时,可以测试新版本,对代码进行必要的更改,然后在进行升级。
Maven
也支持所谓的版本管理(version management)
。在父 POM
中,我们可以用 <dependencyManagement>
元素定义一个或多个依赖项的版本,然后在项目的各个模块中引用它们,无需在每个模块中指定版本。这种方法对于确保项目的各个部分使用相同的依赖版本非常有效。
结论
虽然范围版本提供了寻找需要的库的新版本的方便,但大范围的未定版本和更新可能会引入不希望的结果,这些结果可能导致编译异常或者运行时错误。
我们需要使用正确的方法来管理和锁定我们的依赖,避免这些困扰,并保持我们的项目的稳定性。