【问题标题】:Maven: how to override dependencyMaven:如何覆盖依赖项
【发布时间】:2018-08-03 07:00:52
【问题描述】:

我的情况有点奇怪:

在 pom 中具有工件 id: yyy 的依赖项(见下文)具有依赖项:

<dependency>
   <groupId>javax.servlet</groupId>
   <artifactId>javax.servlet-api</artifactId>
   <version>2.5</version>
</dependency>

所以问题是我需要在当前模块中使用 3.1.0 版本,因为它有额外的功能:

<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>3.1.0</version>
</dependency>

我已经尝试了页面示例中解释的排除标记和依赖管理标记:Maven: how to override the dependency added by a library

它不起作用。我也阅读并尝试了本文中的 3 个示例:https://spring.io/blog/2016/04/13/overriding-dependency-versions-with-spring-boot

它也没有工作。所以我所做的就是重新排序我的 pom 依赖项,以便 3.1.0 在具有工件 yyy 的那个之前运行,我很高兴它成功地构建了一个干净的安装。我的幸福是短暂的,因为在全新安装后 pom 重新排序,并且 3.1.0 自动重新排序到 yyy 下面。这意味着下一次构建将再次使用 2.5 并失败。

我的pom结构sn-p如下:

<dependencies>
  <dependency>
    <groupId>xxxx.xxx.xxxx</groupId>
    <artifactId>yyy</artifactId>
    <version>1.0.0</version>
  </dependency>
  <dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>3.1.0</version>
  </dependency>
<dependencies>

【问题讨论】:

  • 猜猜这可能会有所帮助,*.com/questions/793054/maven-classpath-order-issues
  • 请解释一下:“它不起作用”是什么意思......
  • 自己添加依赖项(作为直接依赖项,或在依赖项管理中)应该可以解决问题。如果不是,我想还有其他事情困扰您
  • @khmarbaise 我的意思是它选择了 javax.servlet-api 的 2.5 版本
  • 你需要显示完整的 pom 文件,除了它可能是另一个依赖项的传递依赖项......

标签: java maven dependency-management


【解决方案1】:

我的幸福是短暂的,因为在全新安装 pom 之后 重新排序,3.1.0 自动重新排序 低于 yyy。这意味着下一次构建将再次使用 2.5 并失败。

请注意,javax.servlet:javax.servlet-api 必须包含在 WAR 中,但只能包含在包含和引导 servlet 容器的独立 JAR 中。
如果您构建标准 WAR,则必须使用服务器提供的依赖项。因此,应该使用provided 范围声明依赖项。

我已经尝试了排除标签和依赖管理标签的解释 在页面上的示例中:Maven:如何覆盖依赖项 由图书馆添加

dependencyManagement 在这里将无能为力,因为该问题与您在 dependencyManagement 元素之外包含的依赖项有关。
但是在dependency 声明中使用exclusions 选项是正确的方法。如果以这种方式使用,它应该排除 javax.servlet-api 工件的 2.5 版本:

<dependencies>
  <dependency>
    <groupId>xxxx.xxx.xxxx</groupId>
    <artifactId>yyy</artifactId>
    <version>1.0.0</version>
    <exclusions>
      <exclusion>
        <artifactId>javax.servlet</artifactId>
        <groupId>javax.servlet-api</groupId>
      </exclusion>
    </exclusions>
  </dependency>
  <dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>3.1.0</version>
  </dependency>
</dependencies>

如果问题仍然存在,则表示该依赖项可能被另一个依赖项拉取。
一些通常有助于发现的提示:

  • 检查您没有使用 WAR 覆盖功能。但这里不太可能,因为您只检索 1 个版本的依赖项

  • 在 WAR 项目上使用 mvn dependency:tree 检查所有拉取的依赖项。
    为了便于阅读,您也可以这样过滤:
    mvn dependency:tree -Dincludes=javax.javax.servlet-api

【讨论】:

    【解决方案2】:

    下面的解决方案忽略了 2.5 版,因此可以正常工作。不过我不知道是什么意思。它是否删除了其他依赖项?请用简单的英语解释 groupId 和 artifactId 中的星号是什么意思。我想知道风险,因为我使用的是多模块系统,其中在其他依赖项中有许多嵌套依赖项。我将继续研究,但如果有人可以解释,请做。谢谢

        <dependencies> 
          <dependency>
             <groupId>xxxx.xxx.xxxx</groupId>
             <artifactId>yyy</artifactId>
             <version>1.0.0</version>
             <exclusions> 
                <exclusion> 
                  <groupId>javax.servlet</groupId>  // this works or 
                  <groupId>*</groupId> // this works
                  <artifactId>*</artifactId> // this part was a mandatory *
                </exclusion> 
             </exclusions> 
          </dependency> 
          <dependency>
             <groupId>javax.servlet</groupId>
             <artifactId>javax.servlet-api</artifactId>
             <version>3.1.0</version>
          </dependency>
        </dependencies> 
    

    【讨论】: