【问题标题】:Maven - Detect Multiple Versions of the Same DependencyMaven - 检测相同依赖项的多个版本
【发布时间】:2012-04-05 13:00:11
【问题描述】:

我刚刚经历了一个案例,我的 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 并没有在这方面失败,甚至警告(或者如果确实如此,我从未见过!)这样的事情正在发生......因此我从未注意到它,直到调试 jersey 版本时发生的问题 - jclouds 依赖引入的 core 导致了一些问题。

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

【问题讨论】:

    标签: java maven maven-2 maven-3


    【解决方案1】:

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

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

    【讨论】:

      【解决方案2】:

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

      【讨论】:

      • 你指的是运行依赖:树,详细指定为@DmitryB 建议?
      【解决方案3】:

      使用 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>
      

      【讨论】:

      • 这似乎正是我想要的。我没想过要为此检查执行器插件。
      【解决方案4】:

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

      <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 通过支持最接近依赖根的依赖来解决版本冲突。

      【讨论】:

      • 我知道如何解决这个问题。我想要的是让 maven 告诉我有一个潜在的问题开始。
      【解决方案5】:

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

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

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

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

      在这种情况下,如果两个模块都是使用它们的依赖项构建和部署的 - 你会遇到冲突,但它是一种强制插件不知道如何检测的。由于项目 A 不(不能)依赖其子模块。

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

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

      【讨论】:

        【解决方案6】:

        @维塔利

        我快速手工制作的命令行来检测同一依赖项的多个版本:

        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
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2016-05-24
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多