如何在Maven中从父项目中排除依赖项?

时间:2011-10-26 03:28:08

标签: java maven

例如,我有2个Maven项目。一个是“项目 - 父母”。另一个是“项目孩子”。显然,“项目 - 孩子”是“项目 - 父母”的子项目。

“project-parent”具有log4j的依赖关系。但是我想把它从“项目孩子”中排除。有办法吗?

您可能会说我应该将log4j从“project-parent”移动到“project-child”。这是完全正确的。 但假设我无法修改“project-parent”的POM。

提前致谢。

6 个答案:

答案 0 :(得分:12)

我不知道实际排除依赖关系的方法,但您可以将其从目标分发中排除,但这有点像黑客攻击。您需要将依赖关系的范围更改为可以在最终分发中排除的内容。

所以,说我的父母依赖于junit 4.8,在我的pom中你说:

<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.8</version>
    <scope>provided</scope>
</dependency>

所以我们正在改变提供的范围。有关其工作原理的说明,请参阅我对NoClassDefFoundError: org/junit/AfterClass during annotation processing的回答。不幸的是,这不会影响构建,但是当您复制最终分发的依赖项时,可以使用excludeScope配置元素不将依赖项复制到最终分发中:

<plugin>
<artifactId>maven-dependency-plugin</artifactId>

<executions>
    <execution>
        <id>copy-libs</id>
        <phase>package</phase>
        <goals>
            <goal>copy-dependencies</goal>
        </goals>
        <configuration>
            <outputDirectory>${project.build.directory}/lib</outputDirectory>
            <excludeScope>provided</excludeScope>
        </configuration>
    </execution>

答案 1 :(得分:10)

我认为在Maven2中没有办法实现这一点,因为这就是POM继承的用途 。然而,我可以想到一个技巧:

假设您有权将工件上传到内部工件存储库。您可以创建一个空的JAR,将其部署为log4j:log4j,具有明显异常的版本(例如log4j:log4j:9999)。在project-child中添加这样的依赖项。然后它将覆盖parent的依赖关系取决于实际上为空的JAR。

答案 2 :(得分:1)

如果我理解了这个问题,你需要的是以下内容。它引入了一个依赖项,并将该依赖项排除在添加到其依赖项列表之外。如果您想要注入较新版本的软件包而不是另一个软件包中引用的软件包,通常会使用此方法。

<dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>1.2.15</version>
    <exclusions>
        <exclusion>
            <groupId>com.sun.jmx</groupId>
            <artifactId>jmxri</artifactId>
        </exclusion>
        ...
    </exclusions>
    ...

如果您正在谈论<parent>关系,那么我不确定是否有办法做到这一点。你可以从<parent>切换到<dependency>吗?

答案 3 :(得分:1)

我和你一样遇到了同样的问题。 在我的项目中,让我们调用父pom是parent.pom。 parent定义了log4j,slf4j,如下所示:

       <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>${slf4j-api.version}</version>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>${log4j.version}</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>jcl-over-slf4j</artifactId>
            <version>${slf4j-api.version}</version>
        </dependency>

        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>${slf4j-log4j12.version}</version>
        </dependency>

子项目在child.pom中调用一些依赖项。但我不想要log4j-1.2.x依赖,并希望增加slf4j的版本。

因此。我添加了父

的依赖关系
<dependency>
        <groupId>parent</groupId>
        <artifactId>myartifactId</artifactId>
        <version>${my parent version}</version>
</dependency>

并使用排除删除 log4j

<dependency>
        <groupId>parent</groupId>
        <artifactId>myartifactId</artifactId>
        <version>${my parent version}</version>
        <exclusions>
            <exclusion>
                <groupId>log4j</groupId>
                <artifactId>log4j</artifactId>
            </exclusion>
        </exclusions>
</dependency>

并在子pom中明确添加slf4j和log4j2的依赖

 <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
        <version>1.7.6</version>
    </dependency>
    <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-slf4j-impl</artifactId>
        <version>2.8.2</version>
    </dependency>
    <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-api</artifactId>
        <version>2.8.2</version>
    </dependency>

    <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-core</artifactId>
        <version>2.8.2</version>
    </dependency>

    <dependency>
        <groupId>com.lmax</groupId>
        <artifactId>disruptor</artifactId>
        <version>3.3.4</version>
    </dependency>

然后使用 mvn依赖:树来显示依赖列表,仍然可以看到log4j

[INFO] +- org.apache.kafka:kafka_2.10:jar:0.8.2.0:compile
[INFO] |  +- com.yammer.metrics:metrics-core:jar:2.2.0:compile
[INFO] |  +- org.scala-lang:scala-library:jar:2.10.4:compile
[INFO] |  +- org.apache.zookeeper:zookeeper:jar:3.4.6:compile
[INFO] |  |  +- org.slf4j:slf4j-log4j12:jar:1.7.5:compile
[INFO] |  |  +- log4j:log4j:jar:1.2.17:compile

好吧,让我们在该依赖项上添加排除项...删除此人。

    <dependency>
        <groupId>org.apache.kafka</groupId>
        <artifactId>kafka-clients</artifactId>
        <version>0.10.1.1</version>
        <exclusions>
            <exclusion>
                <groupId>log4j</groupId>
                <artifactId>log4j</artifactId>
            </exclusion>
        </exclusions>
    </dependency>

然后再次运行该命令以检查依赖项列表。好!明确〜

希望能帮到你:&gt;

答案 4 :(得分:0)

实现这一目标的一种方法是在项目子项中指定依赖项,但使用&#39; test&#39;范围(或任何最轻的范围可用)。这将&#34;隐藏&#34;在project-parent中指定的作用域,使其仅可用于测试代码,并且在编译和运行时都不可用于非测试代码。

我偶然发现了这个错误功能。在我的情况下,我的项目孩子有一个项目兄弟与编译&#39;范围依赖,而project-parent具有相同的依赖关系(实际上是从祖父母继承的),并提供了&#39;范围。 project-child是一个可执行文件但是依赖于project-sibling,因此在运行时从project-sibling抛出NoClassDefFoundError,因为正在使用project-child的运行时类路径,它没有包含&# 39;设置&#39;依赖。我通过移动&#39;编译来解决这个问题。从项目兄弟到项目父对象的依赖关系,以便编译&#39;会&#34;隐藏&#34;提供了&#39;。

答案 5 :(得分:0)

我设法从父pom中排除了暂时依赖。通过在<dependencymanagement>中重新导入它,然后从我想要的依赖项中设置排除项。像这样:

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <version>${spring-boot.version}</version>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>junit</groupId>
                    <artifactId>junit</artifactId>
                </exclusion>
            </exclusions>
        </dependency>