V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
different
V2EX  ›  Java

关于 maven 的子 pom 为何无法继承父 pom 的依赖?

  •  
  •   different · 2019-11-22 17:55:06 +08:00 · 8639 次点击
    这是一个创建于 1588 天前的主题,其中的信息可能已经有所发展或是发生改变。

    父 pom 中写了 ............

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

    ............

    子 pom ............ <parent></parent>

        <artifactId>aispringcloud</artifactId>
        
        <groupId>com.southwind</groupId>
        
        <version>1.0-SNAPSHOT</version>
        
    </parent>
    

    ............

    继承父的 pom

    然后运行子项目的时候,必须重新在子的 pom 写,否者报错。

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

    这是为什么?

    我是照着视频打的代码,子工程是一个 zipkin,然后视频作者这么解析的: Spring Cloud 不同版本中具体操作有一些区别,很多组件之间是不兼容的,基于这个版本的 zipkin,需要单独引入.

    难道从父 pom 继承下来的和单独引入的不是同一个吗?

    求指点...

    30 条回复    2020-04-20 10:33:57 +08:00
    Leonard
        1
    Leonard  
       2019-11-22 18:01:27 +08:00   ❤️ 4
    看成子 porn 和父 porn 了
    mepine
        2
    mepine  
       2019-11-22 18:04:52 +08:00   ❤️ 1
    @Leonard 同 😂
    snappyone
        3
    snappyone  
       2019-11-22 18:06:31 +08:00 via Android
    用 dependencymgmt 了吗
    wolfie
        4
    wolfie  
       2019-11-22 18:12:39 +08:00
    父项目 mvn install
    nthin0
        5
    nthin0  
       2019-11-22 18:18:11 +08:00 via iPhone
    父 pom 是不是写在 dependencyManagement 里了
    different
        6
    different  
    OP
       2019-11-22 18:55:31 +08:00 via Android
    @nthin0
    @snappyone
    写在 Dependencies
    different
        7
    different  
    OP
       2019-11-22 18:56:02 +08:00 via Android
    @wolfie 我试试
    732870147
        8
    732870147  
       2019-11-22 18:58:30 +08:00 via Android
    下班,散光眼,Porn!?
    snappyone
        9
    snappyone  
       2019-11-22 19:10:54 +08:00
    @different Dependencies 不行,参照 5 楼用 dependencyManagement
    different
        10
    different  
    OP
       2019-11-22 19:30:08 +08:00 via Android
    @snappyone 那父工程目录下的 dependencies 有啥用?父工程下又没有直接的代码,只有子项目
    Aruforce
        11
    Aruforce  
       2019-11-22 20:02:46 +08:00 via Android
    如果我理解正确的话…
    父 pom 只是用来管理统一版本…dependencies 是不会向下传递的… pom 的依赖传递是向上的…
    wolfie
        12
    wolfie  
       2019-11-22 20:03:25 +08:00
    找不到父项目依赖。
    先找本地仓库,在找服务端仓库。
    mvn install 到本地你的子项目才会找到父项目。

    另外 `dependencies` 是对的,`dependencyManagement` 中的依赖子项目不会默认继承。
    Aruforce
        13
    Aruforce  
       2019-11-22 20:09:55 +08:00 via Android
    @wolfie dependencyManagement 是用来限定依赖版本…子工程可以重新指定版本… dependencies 应该不会向下传递…向下传递不合理…
    wolfie
        14
    wolfie  
       2019-11-22 20:13:40 +08:00
    @Aruforce #13
    > 这就体现了 dependencyManagement 和 dependencies 的一些区别,如果在父类中定义了 dependencies, [子类继承的时候回自动产生依赖] ,而 dependencyManagement 中的东西就像是依赖的声明,子模块想要继承还需要在自己的 pom 文件中进行添加。

    随便搜的
    写在父项目的好处是就是不用重复依赖。
    Aruforce
        15
    Aruforce  
       2019-11-22 20:14:02 +08:00 via Android
    Lz 你可以在 子工程里面执行。mvn help:effective-pom。看下 如果有 Jar 不是你想要的版本…可以 父 pom dependency management 里面 exclusion 掉 指定你要的版本…
    hantsy
        16
    hantsy  
       2019-11-22 20:14:06 +08:00   ❤️ 1
    dependencies 会继承,慎用。如果子 POM 恰好不需要某依赖,但 parent dependencies 声明了,会造成污染。如果你有对代码洁癖的习惯,还是不要用它继承。

    dependencyManagement 不会继承。一般用于 Parent POM,主要用来管理整个项目树型结构的依赖版本,使保持一致性,防止不同版本的依赖在打包时冲突。最好的方法是 Parent POM 用它声明,Child Pom 在 dependencies 中加入相应依赖,不需要再声明 Version。
    Aruforce
        17
    Aruforce  
       2019-11-22 20:17:21 +08:00 via Android
    @wolfie 我是只用父 pom 限定 jar 版本 …没在里面加过 dependencies…依赖向下传递有点违反我的直觉… 我回去了试下…能不能向下传递吧…
    liangkang1436
        18
    liangkang1436  
       2019-11-22 21:42:04 +08:00
    https://stackoverflow.com/questions/2619598/differences-between-dependencymanagement-and-dependencies-in-maven

    I'm fashionably late to this question, but I think it's worth a clearer response than the accepted one (which is correct, but doesn't emphasize the actual important part, which you need to deduce yourself).
    In the parent POM, the main difference between the <dependencies> and <dependencyManagement> is this:
    Artifacts specified in the <dependencies> section will ALWAYS be included as a dependency of the child module(s).
    Artifacts specified in the <dependencyManagement> section, will only be included in the child module if they were also specified in the <dependencies> section of the child module itself. Why is it good you ask? because you specify the version and/or scope in the parent, and you can leave them out when specifying the dependencies in the child POM. This can help you use unified versions for dependencies for child modules, without specifying the version in each child module.
    Aruforce
        19
    Aruforce  
       2019-11-22 22:13:10 +08:00
    @Aruforce @wolfie
    奇怪了 真的可以 啊....
    子工程不想使用父工程某些依赖怎么排除掉 ?
    按照 @liangkang1436 的说明 似乎是无法排除?让人不爽...
    我还是不这么干了...
    gtexpanse
        20
    gtexpanse  
       2019-11-22 22:19:48 +08:00
    尽量不要在 parent pom 里写<dependencies>,除非你真的确定所有 child 项目都*必须*有这个依赖
    different
        21
    different  
    OP
       2019-11-22 22:41:58 +08:00
    @wolfie 不好意思,刚刚有事去忙了,现在执行了 mvn install 之后依旧不行。
    删掉子 pom 的 web 依赖之后,报错。

    SLF4J: Actual binding is of type [org.apache.logging.slf4j.Log4jLoggerFactory]

    Exception in thread "main" java.lang.StackOverflowError

    at java.base/java.util.stream.Sink$ChainedReference.cancellationRequested(Sink.java:263)

    at java.base/java.util.stream.Sink$ChainedReference.cancellationRequested(Sink.java:263)


    @Aruforce

    我也是看着视频写的代码,实际上我并不知道何种原因导致错误,,只是感觉,既然父 pom 有了 dependencies 包含了 web 包,子 pom 就可以不需要 web 包了。 [查了资料的确如此,但是在运行的时候,却必须要在子 pom 再依赖一次 web 包]
    执行了,mvn help:effective-pom 可以看到一堆依赖,但是根据报错信息,应该是和 log 包有关,但是无论我加不加 web 依赖,只能搜索到和日志相关的这个包:
    <dependency>

    <groupId>org.springframework.integration</groupId>

    <artifactId>spring-integration-syslog</artifactId>

    <version>5.1.2.RELEASE</version>

    </dependency>
    Xbluer
        22
    Xbluer  
       2019-11-22 22:44:39 +08:00
    @Aruforce #19 排除的标签 exclusions

    Spring Boot 中使用 Log4j2 的时候一般需要用到

    <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter</artifactId>
    <exclusions>
    <exclusion>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-logging</artifactId>
    </exclusion>
    </exclusions>
    </dependency>
    different
        23
    different  
    OP
       2019-11-22 22:45:02 +08:00
    父 pom
    ```
    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.southwind</groupId>
    <artifactId>aispringcloud</artifactId>
    <packaging>pom</packaging>
    <version>1.0-SNAPSHOT</version>
    <modules>
    <module>eurekaserver</module>
    <module>eurekaclient</module>
    <module>resttemplate</module>
    <module>consumer</module>
    <module>zuul</module>
    <module>ribbon</module>
    <module>feign</module>
    <module>hystrix</module>
    <module>nativeconfigserver</module>
    <module>nativeconfigclient</module>
    <module>configserver</module>
    <module>configclient</module>
    <module>zipkin</module>
    <module>zipkinclient</module>
    </modules>
    <!-- 这是 Spring Boot 的父级依赖,这样当前的项目就是 Spring Boot 项目了。-->
    <!-- spring-boot-starter-parent 是一个特殊的 starter,它用来提供相关的 Maven 默认依赖。-->
    <!-- 使用它之后,常用的包依赖可以省去 version 标签。(在 dependencies 里面)-->
    <!-- https://blog.csdn.net/niceyoo/article/details/90731133-->
    <!-- 在 dependencies 里的部分配置可以不用填写 version 信息,-->
    <!-- 这些 version 信息会从 spring-boot-dependencies 里得到继承。-->
    <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.1.2.RELEASE</version>
    </parent>
    <!-- https://blog.csdn.net/hanglife/article/details/90035083-->
    <!-- dependencies 和 dependencyManagement 的区别概述-->

    <dependencies>
    <dependency>
    <groupId>org.springframework.boot</groupId>
    <!-- spring-boot-starter-web 会自动嵌入 tomcat 容器。-->
    <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <!-- 解决 jdk9 以上没有 JAXB API 的问题 (引入下面 4 个包) -->
    <dependency>
    <groupId>javax.xml.bind</groupId>
    <artifactId>jaxb-api</artifactId>
    <version>2.3.0</version>
    </dependency>
    <dependency>
    <groupId>com.sun.xml.bind</groupId>
    <artifactId>jaxb-impl</artifactId>
    <version>2.3.0</version>
    </dependency>
    <dependency>
    <groupId>com.sun.xml.bind</groupId>
    <artifactId>jaxb-core</artifactId>
    <version>2.3.0</version>
    </dependency>
    <dependency>
    <groupId>javax.activation</groupId>
    <artifactId>activation</artifactId>
    <version>1.1.1</version>
    </dependency>
    <dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <!-- <version>1.18.6</version>-->
    <optional>true</optional>
    <!-- https://blog.csdn.net/blueheart20/article/details/81014116-->
    <!-- <scope>provided</scope>-->
    </dependency>
    </dependencies>

    <!-- 锁定版本,并不会真的引入 jar 包 -->
    <dependencyManagement>
    <dependencies>
    <dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-dependencies</artifactId>
    <version>Finchley.SR2</version>
    <type>pom</type>
    <!-- import 范围只有在 denpendencyManagement 元素下才有效果-->
    <!-- https://blog.csdn.net/lqzxpp/article/details/79640638-->
    <scope>import</scope>
    </dependency>
    </dependencies>
    </dependencyManagement>
    </project>

    ```










    子 pom
    ```
    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
    <artifactId>aispringcloud</artifactId>
    <groupId>com.southwind</groupId>
    <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>zipkin</artifactId>

    <dependencies>
    <!-- 父工程不是已经有了吗?为什么还要引入一次?-->
    <dependency>
    <groupId>org.springframework.boot</groupId>
    <!-- spring-boot-starter-web 会自动嵌入 tomcat 容器。-->
    <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
    <groupId>io.zipkin.java</groupId>
    <artifactId>zipkin-server</artifactId>
    <version>2.12.3</version>

    </dependency>
    <!--图形界面展示-->
    <dependency>
    <groupId>io.zipkin.java</groupId>
    <artifactId>zipkin-autoconfigure-ui</artifactId>
    <version>2.12.3</version>
    </dependency>


    </dependencies>
    </project>

    ```
    different
        24
    different  
    OP
       2019-11-22 22:46:01 +08:00
    奇怪了,这 markdown 为何没高亮,,,,姿势不对吗
    different
        25
    different  
    OP
       2019-11-22 22:48:37 +08:00
    @Xbluer exclusions 可以解决包冲突问题吧?但是也无法解析为何子 pom 仍然需要重新引入一次 web 包吧?
    Aruforce
        26
    Aruforce  
       2019-11-23 10:55:50 +08:00 via Android
    @Xbluer 我说的不是这个…是从父 pom dependencies 的依赖被强制的引入到子工程的那些 dependency 没有办法排除…
    pan176
        27
    pan176  
       2019-11-23 20:33:24 +08:00
    子 pom 会继承父 pom。
    你尝试把 .idea 文件夹删掉,重新导入 pom,我就是用这种方法解决怪异现象的。
    different
        28
    different  
    OP
       2019-11-23 21:03:23 +08:00
    @pan176 尴尬,依旧不行
    xb7420
        29
    xb7420  
       2020-04-20 09:54:54 +08:00
    我也遇到了,最终使用 idea 菜单下 File->invalidate caches / restrat ... 解决
    different
        30
    different  
    OP
       2020-04-20 10:33:57 +08:00
    @xb7420 后来我查了一下依赖,发现只要父 pom 和子 pom 都不单独引入 web 包就不会出现报错。总的原因导致应该是 log4j-slf4j-impl 先于 logback-classic 加载而报错。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   963 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 31ms · UTC 20:40 · PVG 04:40 · LAX 13:40 · JFK 16:40
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.