我刚刚遇到了一个我的maven项目的两个直接依赖项,它有两个不同版本的特定传递依赖。
在我的特定情况下,我直接依赖于以下内容:
<dependency>
<groupId>org.jclouds.driver</groupId>
<artifactId>jclouds-sshj</artifactId>
<version>${jclouds.version}</version>
</dependency>
和
<dependency>
<groupId>org.mule.modules</groupId>
<artifactId>mule-module-jersey</artifactId>
<version>${mule.version}</version>
</dependency>
这两个依赖项对com.sun.jersey:jersey-core都有(深层)传递依赖,但每个依赖项都有不同的版本。 Maven没有对此失败,甚至发出警告(或者如果有的话,我从未见过它!)这样的事情正在发生......因此我从未注意到它直到调试发生在版本的球衣时发生的问题 - 由jclouds依赖带来的核心导致一些事情破裂。
是否存在maven插件或其他一些工具,它会检测到这种深度传递依赖性覆盖并至少警告用户(或者maven执行失败)如果它检测到这样的冲突......即使是默认值maven行为只是选择解析依赖项时出现的第一个版本?
答案 0 :(得分:27)
使用Dependency Enforcer插件。当依赖关系没有正确收敛时,它将停止构建。
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
<version>1.0.1</version>
<executions>
<execution>
<id>enforce</id>
<configuration>
<rules>
<DependencyConvergence />
</rules>
</configuration>
<goals>
<goal>enforce</goal>
</goals>
</execution>
</executions>
</plugin>
答案 1 :(得分:5)
@Clement P为您提供了一个非常好的答案。但请注意,对于多模块项目可能不够。
enforcer插件的depedndencyconvergence目标知道如何检测传递依赖性冲突,但是碰撞可能以不同的方式隐藏自己。
假设您有一个多模块项目。 Root是A,它有2个子模块,B1和B2。
B1声明对工件的依赖 a:b:c: 1.1 ,而B2声明对工件的依赖 a:b:c: 2.0
在这种情况下,如果两个模块都是使用它们的依赖项构建和部署的 - 那么您将发生冲突,但它是一种执行器插件不知道如何检测的。由于项目A不能(不能)依赖于其子模块。
为了在我们的组织中克服这个问题,我们使用了dependency:list插件并手动分析了它的输出。
流程的粗略描述:运行此目标的输出是项目层次结构中所有项目的所有传递依赖项的列表。我们解析输出,对依赖项进行排序,并仅搜索那些仅由版本ID不同的工件。这需要在您的CI环境中使用一些脚本,但这是现在获得整体情况的唯一方法。
答案 2 :(得分:4)
您可以运行依赖关系报告或使用依赖关系树:
mvn依赖:tree -Dverbose -Dincludes = commons-collections
答案 3 :(得分:2)
您可以查看dependency hiercharchy
概述。这不会警告您,但您可以看到是否为同一个库的较新版本丢弃了某些版本。
答案 4 :(得分:1)
您可以通过从适当的依赖项中排除非需要的版本来解决版本冲突。例如:
<dependency>
<groupId>org.jclouds.driver</groupId>
<artifactId>jclouds-sshj</artifactId>
<version>${jclouds.version}</version>
<exclusions>
<exclusion>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-core</artifactId>
</exclusion>
</exclusions>
</dependency>
或者将com.sun.jersey:jersey-core与所需版本添加到依赖项中。 Maven通过支持最接近依赖关系root的依赖来解决版本问题。
答案 5 :(得分:0)
@Vitaly
我快速手工制作的命令行,用于检测同一依赖项的多个版本:
mvn dependency:tree | grep ":compile" | sed 's/.* \(.*\):compile/\1/' | sort -u | cut -d ':' -f '1 2' | uniq -c | grep -vE "^ *1"
然后,我们可以使用以下命令行来获取这些依赖项的已使用版本(它不是优化的命令行;):
for dep in $(mvn dependency:tree | grep ":compile" | sed 's/.* \(.*\):compile/\1/' | sort -u | cut -d ':' -f '1 2' | uniq -c | grep -vE "^ *1" | cut -d ' ' -f 8);
do
echo $dep;
mvn dependency:tree | grep $dep;
echo
done