简体   繁体   English

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

[英]How to exclude a dependency from parent's project in Maven?

For example, I have 2 Maven projects.例如,我有 2 个 Maven 项目。 One is "project-parent".一种是“项目父母”。 The other is "project-child".另一个是“项目孩子”。 Obviously, "project-child" is the sub project of "project-parent".显然,“project-child”是“project-parent”的子项目。

"project-parent" has a dependency of log4j. “project-parent”具有 log4j 的依赖关系。 But I want to exclude it from the "project-child".但我想将它从“项目子”中排除。 Is there a way?有办法吗?

You might say I should move log4j from "project-parent" to "project-child".你可能会说我应该将 log4j 从“project-parent”移动到“project-child”。 That is totally correct.这是完全正确的。 But the assumption is I CANNOT modify "project-parent"'s POM.但假设是我不能修改“project-parent”的 POM。

Thanks in advance.提前致谢。

I think in Maven2 there is no way to achieve this, because this is what POM inheritance is for .我认为在 Maven2 中没有办法实现这一点,因为这就是 POM 继承的用途。 However there is one trick that I can think of:但是,我能想到一个技巧:

Assume you have the right to upload artifact to your internal artifact repository.假设您有权将工件上传到您的内部工件存储库。 You may create an empty JAR, deploy it as log4j:log4j, with a obviously abnormal version (eg log4j:log4j:9999 ).您可以创建一个空 JAR,将其部署为 log4j:log4j,具有明显异常的版本(例如 log4j:log4j:9999 )。 Add such dependency in your project-child.在您的项目子项中添加此类依赖项。 Then it will override the dependency of parent to depends on a in-fact-empty JAR.然后它将覆盖父项的依赖项,使其依赖于一个实际上为空的 JAR。

I don't know of a way of actually excluding a dependency, but you can exclude it from the target distribution, but it's a bit of a hack.我不知道实际上排除依赖项的方法,但是您可以将其从目标分发中排除,但这有点小技巧。 You need to change the scope of the dependency to something that you can exclude in the final distribution.您需要将依赖项的范围更改为可以在最终分发中排除的内容。

So, say that my parent had a dependency on junit 4.8, in my pom you say:所以,假设我的父母依赖于 junit 4.8,在我的 pom 中你说:

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

So we're changing the scope to provided.因此,我们将范围更改为提供。 For an explanation of how this works, see my answer to NoClassDefFoundError: org/junit/AfterClass during annotation processing .有关其工作原理的说明,请参阅我对NoClassDefFoundError: org/junit/AfterClass during annotation processing的回答。 Unfortunately, this doesn't affect the build, but when you're copying the dependencies for the final distribution, you can use the excludeScope configuration element to not copy the dependency into the final distribution:不幸的是,这不会影响构建,但是当您为最终分发复制依赖项时,您可以使用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>

I have met the same question just like you.我遇到了和你一样的问题。 In my project, let call the parent pom is parent.pom.在我的项目中,让调用父pom是parent.pom。 parent defined the log4j, slf4j like this: 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 project invoke some dependency in child.pom.子项目调用 child.pom 中的一些依赖项。 But I don't want the log4j-1.2.x dependency and want to increase the version of slf4j.但是我不想要log4j-1.2.x依赖,想要增加slf4j的版本。

So.所以。 I add the dependency of parent我添加了父级的依赖

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

and use exclusions to remove the log4j并使用排除项删除log4j

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

and explicitly add the slf4j and log4j2's dependency in child pom并在子 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>

then use mvn dependency:tree to show the dependency list, still see the log4j然后使用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

well, let's add the exclusions on that dependency...remove this guy.好吧,让我们添加该依赖项的排除项...删除这个人。

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

then run the command again to check the dependency list.然后再次运行该命令以检查依赖项列表。 OK!好的! clear~清楚~

Hope that can help you :>希望能帮到你:>

One hacky way to accomplish this is to specify the dependency in project-child but with 'test' scope (or whatever lightest-weight scope is available).实现此目的的一种巧妙方法是在 project-child 中指定依赖项,但使用“测试”范围(或任何可用的最轻量范围)。 This will "hide" the scope specified in project-parent so that it is available only to test code, and unavailable to non-test code at both compile and runtime.这将“隐藏”在 project-parent 中指定的范围,以便它仅可用于测试代码,并且在编译和运行时对非测试代码不可用。

I came across this bug-feature mostly by mistake.我主要是错误地遇到了这个错误功能。 In my case, my project-child had a project-sibling with a 'compile' scope dependency, while project-parent had the same dependency specified (actually inherited from a grandparent) with 'provided' scope.在我的例子中,我的 project-child 有一个具有“compile”范围依赖的项目兄弟,而 project-parent 具有指定的相同依赖项(实际上是从祖父母继承的)具有“provided”范围。 project-child was an executable however that depended on project-sibling, and so a NoClassDefFoundError was thrown at runtime from project-sibling since project-child's runtime classpath was being used, which didn't include the 'provided' dependency. project-child 是一个可执行文件,但是它依赖于 project-sibling,因此在运行时从 project-sibling 抛出了 NoClassDefFoundError,因为正在使用 project-child 的运行时类路径,它不包括“提供的”依赖项。 I fixed this by moving the 'compile' dependency from project-sibling to project-parent so that the 'compile' would "hide" the 'provided'.我通过将“编译”依赖项从项目兄弟移动到项目父项来解决此问题,以便“编译”将“隐藏”“提供”。

I have managed to exclude a transient dependency from a parent pom.我已经设法从父 pom.xml 中排除了一个临时依赖项。 By re-importing it in <dependencymanagement> and then setting exclusion por the dependency I wanted out.通过在<dependencymanagement>中重新导入它,然后将排除项设置为我想要的依赖项。 like this eg.:像这样例如:

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

If I understand the question, what you need is something like the following.如果我理解了这个问题,那么您需要的是以下内容。 It pulls in a dependency and excludes that dependency from adding to its dependency list.它引入一个依赖项并将该依赖项从添加到其依赖项列表中排除。 Often this is used if you want to inject a newer version of a package instead of the one referenced in the other package.如果您想注入更新版本的包而不是另一个包中引用的包,通常会使用此方法。

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

If you are instead talking about a <parent> relationship then I'm not sure there is a way to do this.如果您谈论的是<parent>关系,那么我不确定是否有办法做到这一点。 Can you switch from being a <parent> to a <dependency> ?你能从<parent>切换到<dependency>吗?

  1. find out actual base package for your unwanted dependency找出你不需要的依赖的实际基础包

mvn dependency:tree mvn 依赖:树

Analyse this output and find out actual base package for your unwanted dependency分析此输出并找出您不需要的依赖项的实际基本包

  1. now add dependency of base package again in child pom and use exclude tag现在在子 pom 中再次添加基本包的依赖项并使用排除标记
<dependency>
    <groupId>base group id</groupId>
    <artifactId>base artifact id</artifactId>
    <version>version</version>
    <exclusions>
        <exclusion>
            <groupId>your unwanted dependency group id</groupId>
            <artifactId>your unwanted dependency artifact id</artifactId>
        </exclusion>
    </exclusions>
</dependency>
  1. check again再检查一遍

mvn dependency:tree mvn 依赖:树

unwanted dependency should be removed.应该删除不需要的依赖项。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM