143

<exclusions>可以通过在 a 中声明一个元素来排除依赖项中的工件,<dependency>但在这种情况下,需要排除从父项目继承的工件。正在讨论的 POM 摘录如下:

<project>
  <modelVersion>4.0.0</modelVersion>
  <groupId>test</groupId>
  <artifactId>jruby</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <parent>
        <artifactId>base</artifactId>
        <groupId>es.uniovi.innova</groupId>
        <version>1.0.0</version>
    </parent>

    <dependencies>      
        <dependency>
            <groupId>com.liferay.portal</groupId>
            <artifactId>ALL-DEPS</artifactId>
            <version>1.0</version>
            <scope>provided</scope>
            <type>pom</type>
        </dependency>
    </dependencies>
</project>

baseartifact,取决于 javax.mail:mail-1.4.jar,并且ALL-DEPS依赖于同一库的另一个版本。由于mail.jarfromALL-DEPS存在于执行环境中,虽然没有导出,但与mail.jar父级上存在的相冲突,其范围为compile.

一个解决方案可能是从父 POM 中删除 mail.jar,但是大多数继承 base 的项目都需要它(就像 log4j 的传递依赖项一样)。所以我想做的是简单地从子项目中排除父库base,因为如果是依赖项而不是父 pom ,则可以这样做:

...
    <dependency>
        <artifactId>base</artifactId>
        <groupId>es.uniovi.innova</groupId>
        <version>1.0.0</version>
        <type>pom<type>
        <exclusions>
          <exclusion>
             <groupId>javax.mail</groupId>
             <artifactId>mail</artifactId>
          </exclusion>
        </exclusions>
    </dependency>
...
4

11 回答 11

55

一些想法:

  1. base在这种情况下,也许你不能简单地从父级继承(并声明一个具有排除项的依赖项)。如果您在父 pom 中有很多东西,那就不方便了。

  2. 要测试的另一件事是在父 pom 中使用所需的版本声明工件mail以强制收敛(尽管我不确定这会解决范围问题)。ALL-DEPSdependencyManagement

<dependencyManagement>
  <dependencies>
    <dependency>    
      <groupId>javax.mail</groupId>
      <artifactId>mail</artifactId>
      <version>???</version><!-- put the "right" version here -->
    </dependency>
  </dependencies>
</dependencyManagement>
  1. 或者,mail如果您不使用依赖它的功能,您可以从 log4j 中排除依赖项(这就是我要做的):
<dependency>
  <groupId>log4j</groupId>
  <artifactId>log4j</artifactId>
  <version>1.2.15</version>
  <scope>provided</scope>
  <exclusions>
    <exclusion>
      <groupId>javax.mail</groupId>
      <artifactId>mail</artifactId>
    </exclusion>
    <exclusion>
      <groupId>javax.jms</groupId>
      <artifactId>jms</artifactId>
    </exclusion>
    <exclusion>
      <groupId>com.sun.jdmk</groupId>
      <artifactId>jmxtools</artifactId>
    </exclusion>
    <exclusion>
      <groupId>com.sun.jmx</groupId>
      <artifactId>jmxri</artifactId>
    </exclusion>
  </exclusions>
</dependency>
  1. 或者您可以恢复到 log4j 的 1.2.14 版本,而不是异端的 1.2.15 版本(他们为什么不将上述依赖项标记为可选?!)。
于 2010-04-21T15:28:46.793 回答
35

您可以按照 Sonatypes Best Practicespom的描述将您的依赖项分组到不同的项目中:

<project>
    <modelVersion>4.0.0</modelVersion>
    <artifactId>base-dependencies</artifactId>
    <groupId>es.uniovi.innova</groupId>
    <version>1.0.0</version>
    <packaging>pom</packaging>
    <dependencies>
        <dependency>
            <groupId>javax.mail</groupId>
            <artifactId>mail</artifactId>
            <version>1.4</version>
        </dependency>
    </dependencies>
</project>

并从您的 parent-pom 中引用它们(查看依赖项<type>pom</type>):

<project>
    <modelVersion>4.0.0</modelVersion>
    <artifactId>base</artifactId>
    <groupId>es.uniovi.innova</groupId>
    <version>1.0.0</version>
    <packaging>pom</packaging>
    <dependencies>
        <dependency>
            <artifactId>base-dependencies</artifactId>
            <groupId>es.uniovi.innova</groupId>
            <version>1.0.0</version>
            <type>pom</type>
        </dependency>
    </dependencies>
</project>

您的子项目像以前一样继承了这个父 pom。但是现在,可以在块内的子项目中排除邮件依赖项dependencyManagement

<project>
    <modelVersion>4.0.0</modelVersion>
    <groupId>test</groupId>
    <artifactId>jruby</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <parent>
        <artifactId>base</artifactId>
        <groupId>es.uniovi.innova</groupId>
        <version>1.0.0</version>
    </parent>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <artifactId>base-dependencies</artifactId>
                <groupId>es.uniovi.innova</groupId>
                <version>1.0.0</version>
                <exclusions>
                    <exclusion>
                        <groupId>javax.mail</groupId>
                        <artifactId>mail</artifactId>
                    </exclusion>
                </exclusions>
            </dependency>
        </dependencies>
    </dependencyManagement>
</project>
于 2013-11-12T13:58:26.680 回答
16

不要使用父 pom

这听起来可能很极端,但是“继承地狱”也是一些人背弃面向对象编程(或者更喜欢组合而不是继承)的原因,删除有问题的<parent>块并复制和粘贴你需要的任何东西<dependencies>(如果你的团队给你这种自由)。

应该忽略将 poms 拆分为父母和孩子以“重用”和“避免冗余”的假设,您应该首先满足您的即时需求(治疗比疾病更糟糕)。此外,冗余还有它的优点——即独立于外部变化(即稳定性)。

如果您生成有效的 pom,这比听起来要容易(eclipse 提供了它,但您可以从命令行使用 生成它mvn help:effective)。

例子

我想logback用作我的 slf4j 绑定,但我的父 pom 包含log4j依赖项。我不想去,不得不将其他孩子对 log4j 的依赖推到他们自己的pom.xml文件中,这样我的就没有障碍了。

于 2017-12-21T22:01:02.533 回答
9

scope使用指向空 jar的系统重新定义依赖项(在子 pom 中) :

<dependency>
    <groupId>dependency.coming</groupId>
    <artifactId>from.parent</artifactId>
    <version>0</version>
    <scope>system</scope>
    <systemPath>${project.basedir}/empty.jar</systemPath>
</dependency>

jar 可以只包含一个空文件:

touch empty.txt
jar cvf empty.txt
于 2018-01-04T21:04:31.553 回答
6

您是否尝试过明确声明您想要的 mail.jar 版本?Maven 的依赖解析应该使用它来解析所有其他版本的依赖。

<project>
  <modelVersion>4.0.0</modelVersion>
  <groupId>test</groupId>
  <artifactId>jruby</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <parent>
        <artifactId>base</artifactId>
        <groupId>es.uniovi.innova</groupId>
        <version>1.0.0</version>
    </parent>
    <dependencies>          
        <dependency>
            <groupId>javax.mail</groupId>
            <artifactId>mail</artifactId>
            <version>VERSION-#</version>
            <scope>provided</scope>
        </dependency> 
        <dependency>
            <groupId>com.liferay.portal</groupId>
            <artifactId>ALL-DEPS</artifactId>
            <version>1.0</version>
            <scope>provided</scope>
            <type>pom</type>
        </dependency>
    </dependencies>
</project>
于 2010-04-21T20:51:31.840 回答
3

最好的办法是让你不总是想要继承的依赖关系不传递。

您可以通过在提供范围的父 pom 中标记它们来做到这一点。

如果您仍然希望父级管理这些 deps 的版本,您可以使用<dependencyManagement>标签来设置您想要的版本,而无需显式继承它们,或将该继承传递给子级。

于 2012-10-29T20:01:25.797 回答
2

We can add the parent pom as a dependency with type pom and make exclusion on that. Because anyhow parent pom is downloaded. This worked for me

<dependency>
  <groupId>com.abc.boot</groupId>
  <artifactId>abc-boot-starter-parent</artifactId>
  <version>2.1.5.RELEASE</version>
  <type>pom</type>
  <exclusions>
    <exclusion>
      <groupId>com.google.code.gson</groupId>
      <artifactId>gson</artifactId>
    </exclusion>
  </exclusions>   
</dependency>
于 2019-12-06T14:12:44.847 回答
1

在子 pom.xml 中重复父级的依赖关系并在其中插入排除项:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
    <exclusions>
        <exclusion>
            <groupId>com.vaadin.external.google</groupId>
            <artifactId>android-json</artifactId>
        </exclusion>
    </exclusions>
</dependency>
于 2021-02-11T10:22:53.887 回答
1

当您调用一个包但不想要它的某些依赖项时,您可以执行以下操作(在这种情况下,我不希望添加旧的 log4j,因为我需要使用较新的):

<dependency>
  <groupId>package</groupId>
  <artifactId>package-pk</artifactId>
  <version>${package-pk.version}</version>

  <exclusions>
    <exclusion>
      <groupId>org.apache.logging.log4j</groupId>
      <artifactId>log4j-core</artifactId>
    </exclusion>
    <exclusion>
      <groupId>org.apache.logging.log4j</groupId>
      <artifactId>log4j-api</artifactId>
    </exclusion>
  </exclusions>
</dependency>

<!-- LOG4J -->
<dependency>
  <groupId>org.apache.logging.log4j</groupId>
  <artifactId>log4j-core</artifactId>
  <version>2.5</version>
</dependency>
<dependency>
  <groupId>org.apache.logging.log4j</groupId>
  <artifactId>log4j-api</artifactId>
  <version>2.5</version>
</dependency>

这对我有用......但我对 java/maven 很陌生,所以它可能不是最佳的。

于 2016-06-07T10:01:53.717 回答
1

我真的需要做这件肮脏的事情......这是怎么做的

我用 scope 重新定义了这些依赖项test。范围provided对我不起作用。

我们使用 spring Boot 插件来构建 fat jar。我们有定义通用库的模块common,例如 Springfox swagger-2。我的超级服务需要有父公共(它不想这样做,但公司规则强制!)

所以我的父母或公地有pom。

<dependencyManagement>

    <!- I do not need Springfox in one child but in others ->

    <dependencies>
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version>${swagger.version}</version>
            <exclusions>
                <exclusion>
                    <groupId>com.google.guava</groupId>
                    <artifactId>guava</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
            <version>${swagger.version}</version>
        </dependency>
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-bean-validators</artifactId>
            <version>${swagger.version}</version>
        </dependency>

       <!- All services need them ->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>${junit.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>${apache.poi.version}</version>
        </dependency>
    </dependencies>
</dependencyManagement>

还有我的超级服务pom。

<name>super-service</name>
<parent>
    <groupId>com.company</groupId>
    <artifactId>common</artifactId>
    <version>1</version>
</parent>

<dependencies>

    <!- I don't need them ->

    <dependency>
        <groupId>io.springfox</groupId>
        <artifactId>springfox-swagger2</artifactId>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>io.springfox</groupId>
        <artifactId>springfox-bean-validators</artifactId>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>io.springfox</groupId>
        <artifactId>springfox-core</artifactId>
        <version>2.8.0</version>
        <scope>test</scope>
    </dependency>

    <!- Required dependencies ->

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
     <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
    </dependency>
    <dependency>
        <groupId>org.apache.poi</groupId>
        <artifactId>poi-ooxml</artifactId>
    </dependency>
</dependencies>

这是最终脂肪伪影的大小

82.3 MB (86,351,753 bytes) - redefined dependency with scope test
86.1 MB (90,335,466 bytes) - redefined dependency with scope provided
86.1 MB (90,335,489 bytes) - without exclusion

这个答案也值得一提 - 我想这样做,但我很懒...... https://stackoverflow.com/a/48103554/4587961

于 2019-05-03T12:56:00.913 回答
0

禁用从父级继承的子级工件

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <exclusions>                                               
        <exclusion>
            <groupId>org.springframework.boot</groupId>         
            <artifactId>spring-boot-starter-logging</artifactId> 
        </exclusion>
    </exclusions>
</dependency>

从父级移除特定工件

    <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <exclusions>                                  
        <exclusion>                                     
        <groupId>org.apache.logging.log4j</groupId>         
        <artifactId>log4j-to-slf4j</artifactId>             
        </exclusion>
        <exclusion>                                     
            <groupId>ch.qos.logback</groupId>               
            <artifactId>logback-classic</artifactId>     
        </exclusion>
    </exclusions>
</dependency>
于 2021-12-17T12:54:11.763 回答