Maven – 检测相同依赖关系的多个版本

我刚刚遇到了一个我的maven项目的两个直接依赖项的情况,它有两个不同版本的特定传递依赖项。

在我的特定情况下,我直接依赖于以下内容:

 org.jclouds.driver jclouds-sshj ${jclouds.version}  

   org.mule.modules mule-module-jersey ${mule.version}  

这两个依赖关系都对com.sun.jersey:jersey-core有一个(深层)传递依赖,但每个依赖关系都有不同的版本。 Maven没有对此失败,甚至发出警告(或者如果确实如此,我从未见过它!)这样的事情正在发生……因此我在调试发动机版本时发生的问题之前从未注意到它 – 由jclouds依赖带来的核心导致一些事情破裂。

是否存在maven插件或其他一些工具,它会检测到这种深度传递依赖性覆盖并至少警告用户(或者maven执行失败)如果它检测到这样的冲突…即使默认的maven行为是只选择解析依赖项时出现的第一个版本?

使用Dependency Enforcer插件。 当依赖关系无法正确收敛时,它将停止构建。

   org.apache.maven.plugins maven-enforcer-plugin 1.0.1   enforce       enforce     

@Clement P为您提供了一个非常好的答案。 但请注意,对于多模块项目可能不够。

执行器插件的depedndencyconvergence目标知道如何检测传递依赖性冲突,但是冲突可能以不同的方式隐藏自身。

假设您有一个多模块项目。 Root是A,它有2个子模块,B1和B2。

B1声明对工件a:b:c: 1.1的依赖,而B2声明对工件依赖关系a:b:c: 2.0

在这种情况下,如果两个模块都是使用它们的依赖项构建和部署的 – 那么您将发生冲突,但它是一种执行器插件不知道如何检测的。 由于项目A不(不能)依赖于其子模块。

为了在我们的组织中克服这个问题,我们使用了dependency:list插件并手动分析了它的输出。

流程的粗略描述:运行此目标的输出是项目层次结构中所有项目的所有传递依赖项的列表。 我们解析输出,对依赖项进行排序,并仅搜索那些仅由版本ID不同的工件。 这需要在您的CI环境中使用一些脚本,但这是现在获得整体情况的唯一方法。

您可以运行dependnency报告或使用依赖树:

mvn依赖:tree -Dverbose -Dincludes = commons-collections

你可以看看你的dependency hiercharchy概述。 这不会警告您,但您可以查看是否为同一个库的较新版本丢弃了某些版本。

您可以通过从适当的依赖项中排除非需要的版本来解决版本冲突。 例如:

  org.jclouds.driver jclouds-sshj ${jclouds.version}   com.sun.jersey jersey-core    

或者将com.sun.jersey:jersey-core与所需版本一起添加到依赖项中。 Maven通过支持最依赖于依赖关系的依赖来解决版本问题。

@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