【问题标题】:How to exclude a dependency from parent's project in Maven?如何从 Maven 中的父项目中排除依赖项?
【发布时间】:2011-12-15 10:54:42
【问题描述】:

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

"project-parent" 具有 log4j 的依赖项。但我想将它从“项目子”中排除。有什么办法吗?

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

提前致谢。

【问题讨论】:

    标签: java maven


    【解决方案1】:

    我认为在 Maven2 中没有办法实现这一点,因为这就是 POM 继承的用途 .但是,我能想到一个技巧:

    假设您有权将工件上传到您的内部工件存储库。您可以创建一个空 JAR,将其部署为 log4j:log4j,具有明显异常的版本(例如 log4j:log4j:9999 )。在您的项目子项中添加此类依赖项。然后它将覆盖父项的依赖项,使其依赖于一个实际上为空的 JAR。

    【讨论】:

    • 附注:有人正在做类似的事情,并为这种“空”工件提供了一个公共存储库 (version99.qos.ch)。他们使用99-empty 作为版本。人们认为我建议的方法可以将此作为惯例。
    【解决方案2】:

    我不知道实际排除依赖项的方法,但您可以将其从目标分发中排除,但这有点小技巧。您需要将依赖项的范围更改为可以在最终分发中排除的内容。

    所以,假设我的父母依赖于 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>
    

    【讨论】:

    • 谢谢。我已经从分发包中排除了不需要的依赖项,但是我在 Maven Assembly 插件的 assembly.xml 中使用了 。我正在寻求一种从开发环境中排除不需要的依赖项的方法,例如 Eclipse。 :)
    【解决方案3】:

    我遇到了和你一样的问题。 在我的项目中,让调用父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>
    

    并使用 exclusions 删除 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 dependency:tree显示依赖列表,还是看到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>
    

    然后再次运行该命令以检查依赖项列表。好的!清楚~

    希望能帮到你:>

    【讨论】:

    • 我需要添加标签类型 pom,比如 parentmyartifactId${my parent version}pomlog4jlog4j
    【解决方案4】:

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

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

    如果您谈论的是&lt;parent&gt; 关系,那么我不确定是否有办法做到这一点。你可以从&lt;parent&gt; 切换到&lt;dependency&gt; 吗?

    【讨论】:

    • 我的意思是从父项目继承的依赖,而不是直接依赖的传递依赖作为你的例子。无论如何,非常感谢。 :)
    • 是的,我不确定您是否可以这样做。你看到这个问题了吗:stackoverflow.com/questions/2681759/…
    • 感谢您的链接。我已经读过了。看起来在Maven中没有办法正式。我必须做一些解决方法。
    • 解决方法是什么?因为我也陷入了同样的问题
    【解决方案5】:

    实现此目的的一种巧妙方法是在 project-child 中指定依赖关系,但使用“测试”范围(或任何可用的最轻量范围)。这将“隐藏”在 project-parent 中指定的范围,以便它仅可用于测试代码,并且在编译和运行时对非测试代码不可用。

    我主要是无意间发现了这个错误功能。在我的例子中,我的 project-child 有一个具有“compile”范围依赖的项目兄弟,而 project-parent 具有指定的相同依赖项(实际上是从祖父母继承的)具有“provided”范围。 project-child 是一个可执行文件,但是它依赖于 project-sibling,因此在运行时从 project-sibling 抛出了 NoClassDefFoundError,因为正在使用 project-child 的运行时类路径,它不包括“提供的”依赖项。我通过将 'compile' 依赖项从 project-sibling 移动到 project-parent 来解决此问题,以便 'compile' 将“隐藏” 'provided'。

    【讨论】:

    • 如果允许较低的范围级别,这是实现它的好方法
    【解决方案6】:

    我已经设法从父 pom.xml 中排除了一个临时依赖项。通过在&lt;dependencymanagement&gt; 中重新导入它,然后将排除项设置为我想要的依赖项。比如这样:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-11-30
      • 2021-02-27
      • 1970-01-01
      • 2016-06-11
      • 1970-01-01
      • 2012-02-25
      • 2016-08-11
      相关资源
      最近更新 更多