我工作的地方使用Maven,我们有很多内部库。我们尝试以向后兼容的方式进行更改,但有时我们的某个库需要更新版本的另一个库。如果最终产品最终没有引入更新的库版本,那么这可能会导致问题。
对于每个最终产品,我们都有一个dependencyManagement
部分,声明应该为项目使用哪些版本的传递依赖项。我们这样做,而不是让Maven找出要使用的版本,因为我们想要控制使用哪个版本的库。
即使我们让maven弄清楚应该使用哪个版本的库,也可能会使用旧库,这可能导致ClassNotFoundExceptions等...
当项目的某个依赖项需要更新版本时,是否有Maven插件或方法来确定我的项目是否使用旧版本的依赖项?
有mvn dependency:tree
但我们有很多的依赖关系,而且我不想手动查看巨人列表。
谢谢!
修改
由于我们有很多库,如果最终产品使用库A,B和C,并且A和B都使用不同版本的C,则不会始终使用最新版本的C.来自Introduction to the Dependency Mechanism:
依赖关系中介 - 这决定了依赖关系的版本 将在遇到多个版本的工件时使用。 目前,Maven 2.0仅支持使用"最近的定义" 这意味着它将使用最接近的依赖版本 您的项目在依赖树中。你可以随时保证 版本通过在项目的POM中明确声明它。请注意,如果 两个依赖版本在依赖关系树中处于相同的深度, 直到Maven 2.0.8没有定义哪一个会赢,但从那以后 Maven 2.0.9它在声明中的顺序是:第一个 声明获胜。
答案 0 :(得分:2)
由于我们几乎总是以向后兼容的方式进行更改,因此对我们来说最好的解决方案是确保使用最新版本的依赖项。 Maven Enforcer插件带有"需要上限依赖关系"功能完成了这一点。
来自http://maven.apache.org/enforcer/enforcer-rules/requireUpperBoundDeps.html:
此规则要求解析每个依赖项的版本 在构建期间,等于或高于所有传递依赖 声明。在构建期间解析了每个依赖项的版本 通常是POM中指定的版本或带有的版本 最不可传递的步骤("最近的"定义)。更多 有关Maven依赖关系解析的信息,请参阅Maven站点。
这是一个具体的例子。这将导致构建失败:
<dependencies>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.4.0</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>0.9.9</version>
<!-- Depends on org.slf4j:slf4j-api:1.5.0 -->
</dependency>
</dependencies>
因为该项目将使用slf4j-api运行logback-classic 0.9.9 1.4.0和slf4j-api 1.4.0可能与slf4j-api 1.5.0不兼容。
这是日志消息:
Failed while enforcing RequireUpperBoundDeps. The error(s) are [
RequireUpperBoundDeps error for org.slf4j:slf4j-api:1.4.0 paths to dependency are:
+-test:TestParent:1.0-SNAPSHOT
+-org.slf4j:slf4j-api:1.4.0
and
+-test:TestParent:1.0-SNAPSHOT
+-ch.qos.logback:logback-classic:0.9.9
+-org.slf4j:slf4j-api:1.5.0
]
我们可能会在我们可以开启或关闭的个人资料中设置此插件。
答案 1 :(得分:1)
我不确定是否会有你想问的插件。一般情况下,较新的版本将是您定居的版本,但这并不总是一个硬规则 - 有时您会推出更新的版本,但旧版本实际上就是您的版本需要。
根据我的经验,您必须孤立地处理每个依赖性问题。
我们处理此问题的方法是结合使用您建议的<dependencyManagement/>
部分以及带有<DependencyConvergence/>
规则的Maven Enforcer插件。
The dependencyConvergence rule:
...要求依赖版本号收敛。如果一个项目有 两个依赖项,A和B,都取决于相同的工件C, 如果A依赖于不同版本的C,则此规则将无法构建 那么C的版本取决于B。
基本上,如果您dependency tree
中有同一个lib的2个不同版本,则validate phase
会失败。
所以:
我的方式是 - 我们通常有多个模块Maven
项目,我尝试在父级<dependencyManagement/>
部分定义常见的依赖版本 - EG Spring
,{ {1}}等。然后在子模块级别,根据需要定义专家Jersey
部分。
在我们所有的poms中,我们定义了使用<dependencyManagement/>
规则配置的Maven Enforcer
插件,如下所示:
<dependencyConvergence/>
然后在每个<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
<version>1.3.1</version>
<executions>
<execution>
<id>enforce-versions</id>
<goals>
<goal>enforce</goal>
</goals>
</execution>
</executions>
<configuration>
<rules>
<DependencyConvergence/>
</rules>
<fail>true</fail>
</configuration>
</plugin>
版本中,如果有人添加了一个新的依赖项(或者那里有一个新的传递依赖项)与另一个版本发生冲突,那么您的构建将失败,并且您将会得到一个(略微重复的)依赖性问题日志供你处理。
作为终点,我没有看到Maven Enforcer插件使用得太多,但它有really useful rules的负载以及custom rules的能力。
如果确实是<{1}}的{{1}},总是想要,我确定你可以编写一个简单的规则来执行此操作。
希望这有帮助,
威尔