Maven:如何覆盖库添加的依赖项


116

这是我的一般性问题:

我的项目P依赖于A,后者依赖于B,后者依赖于C,后者依赖于D的1.0.1版本。

D的1.0.1版本存在问题,我想强制使用其他模块。我不知道如何在我的项目的POM中声明这一点,因为我没有直接添加对D的依赖。是C声明了对D的依赖。

重要:在这种情况下,不仅版本会更改,组和工件也将更改。因此,这不仅仅是覆盖依赖项版本的问题,而是排除一个模块并包含另一个模块的问题。

在具体情况下,D是StAX,其1.0.1有一个bug。根据错误中的注释,“通过用stax-api-1.0-2(maven GroupId = javax.xml.stream)替换stax-api-1.0.1(maven GroupId = stax)解决了问题”正在尝试。

因此,D = stax:stax-api:jar:1.0.1,C = org.apache.xmlbeans:xmlbeans:jar:2.3.0

我正在使用maven 2.0.9,以防万一。

mvn依赖项输出:树“

mvn dependency:tree
[..snip..]
[INFO] +- org.apache.poi:poi-ooxml:jar:3.6:compile
[INFO] |  +- org.apache.poi:poi-ooxml-schemas:jar:3.6:compile
[INFO] |  |  +- org.apache.xmlbeans:xmlbeans:jar:2.3.0:compile
[INFO] |  |  |  \- stax:stax-api:jar:1.0.1:compile

在我的项目的POM中,我对“ A”具有以下依赖性:

<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi</artifactId>
    <version>3.6</version>
</dependency>
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi-ooxml</artifactId>
    <version>3.6</version>
</dependency>

提前致谢。

Answers:


100

只需在当前pom中指定版本即可。此处指定的版本将覆盖其他版本。

强制版本
如果在当前POM中使用特定版本声明了版本,则将始终采用该版本-但是,应注意的是,如果它本身依赖于使用传递依赖关系,那么这也会影响下游的其他pom。


资源:


5
目前尚不清楚如何指定版本,因为我没有声明对D的依赖。此外,您提供的第一个链接包含“此文档描述了尚未针对Maven 2.0实现的依赖管理的其余要求,特别是在传递依赖方面。” 在顶部。
wishihadabettername

@wishihadabettername,如其他文档中所述:“您可以在A中对D 2.0显式添加一个依赖关系,以强制使用D 2.0”
Colin Hebert 2010年

1
实际上,您在自己的pom中重复了相同的<dependency>条目。在依赖项中,指定所需的<version>。这将覆盖“更深”的依赖项使用的任何版本。
基思·泰勒

27

或者,您可以仅排除不需要的依赖项。STAX包含在JDK 1.6中,因此,如果您使用的是1.6,则可以完全排除它。

我下面的示例对您来说有点不对-您只需要两个排除项之一,但我不确定哪个是排除项。还有其他版本的Stax,在下面的示例中,我导入A,然后导入B,又导入C&D,每个C&D(通过更多传递依赖项)都导入了不同版本的Stax。因此,由于我对“ A”的依赖,我排除了Stax的两个版本。

<dependency>
  <groupId>a.group</groupId>
  <artifactId>a.artifact</artifactId>
  <version>a.version</version>
  <exclusions>
    <!--  STAX comes with Java 1.6 -->
    <exclusion>
      <artifactId>stax-api</artifactId>
      <groupId>javax.xml.stream</groupId>
    </exclusion>
    <exclusion>
      <artifactId>stax-api</artifactId>
      <groupId>stax</groupId>
    </exclusion>
  </exclusions>
<dependency>

1
需要注意的是,可以使用此传递依赖项,如果需要,排除会导致构建失败。
Bernhard Colby

如果您使用的是现代JDK(即1.6+),并且需要通过传递依赖项包含的stax的较旧版本,则可能会遇到各种各样的可怕的运行时类加载器问题。我的建议:在JDK中使用一个。如果遇到“构建失败”,则说明您依赖某种应升级的古老API。或者:将JDK回滚到1.5。祝你好运。
苏格兰,

10

我也无法排除第三方库中的依赖项。我在排除时使用了scot的方法,但在pom中也将依赖关系添加到了较新的版本中。(我使用了Maven 3.3.3)

因此,对于stAX示例,它看起来像这样:

<dependency>
  <groupId>a.group</groupId>
  <artifactId>a.artifact</artifactId>
  <version>a.version</version>
  <exclusions>
    <!--  STAX comes with Java 1.6 -->
    <exclusion>
      <artifactId>stax-api</artifactId>
      <groupId>javax.xml.stream</groupId>
    </exclusion>
    <exclusion>
      <artifactId>stax-api</artifactId>
      <groupId>stax</groupId>
    </exclusion>
  </exclusions>
<dependency>

<dependency>
    <groupId>javax.xml.stream</groupId>
    <artifactId>stax-api</artifactId>
    <version>1.0-2</version>
</dependency>

10

</dependencies>在root pom标签中添加的内容将包含在root pom的所有子模块中。如果您所有的模块都使用该依赖关系,这就是方法。

但是,如果10个子模块中只有3个使用某种依赖关系,则不希望将此依赖关系包含在所有子模块中。在这种情况下,您可以将依赖项放在中</dependencyManagement>。这样可以确保任何需要依赖项的子模块都必须在自己的pom文件中声明它,但是它们将使用与</dependencyManagement>标签中指定的依赖项相同的版本。

您还可以使用</dependencyManagement>来修改在传递依赖中使用的版本,因为在最上面的pom文件中声明的版本就是将要使用的版本。如果您的项目A包含一个外部项目B v1.0,而该项目又包含另一个外部项目C v1.0,这将很有用。有时会发生在项目C v1.0中发现安全漏洞,并在v1.1中进行了更正,但是B的开发人员更新其项目以使用C v1.1的速度很慢。在这种情况下,您可以简单地声明在项目的根pom中对C v1.1的依赖,一切都会很好(假设B v1.0仍然可以使用C v1.1进行编译)。


1

接受的答案是正确的,但我想加两分钱。我遇到了一个问题,其中我有一个项目A,而项目B是一个依赖项。这两个项目都使用slf4j,但是项目B使用log4j,而项目A使用logback。项目B使用slf4j 1.6.1,而项目A使用slf4j 1.7.5(由于已经包含了logback 1.2.3依赖性)。

问题:在检查eclipe的依赖项层次结构选项卡后,项目A找不到slf4j 1.7.5上存在的函数,我发现在构建期间它正在使用项目B中的slf4j 1.6.1,而不是使用logback的slf4j 1.7.5。 。

我通过更改对项目A pom的依赖关系的顺序解决了该问题,当我将项目B条目移至回送条目下方时,maven开始使用slf4j 1.7.5构建项目。

编辑: 在项目B依赖项也起作用之前添加slf4j 1.7.5依赖项。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.