如何从父pom继承依赖到子pom

Posted

技术标签:

【中文标题】如何从父pom继承依赖到子pom【英文标题】:How to inherit dependency from a parent pom to a child pom 【发布时间】:2016-12-17 08:35:35 【问题描述】:

我是使用 maven 和 jenkins 的新手。我正在尝试将依赖项从父 pom 继承到子 pom 它显示以下错误:

[ERROR] COMPILATION ERROR : 
[INFO] -------------------------------------------------------------
[ERROR] /D:/jenkins/workspace/CBAW/testP/WSW_Investment/src/main/java/com/td/inv/wss/util/XMLConverters.java:[10,26] package com.rpmtec.current does not exist
[ERROR] /D:/jenkins/workspace/CBAW/testP/WSW_Investment/src/main/java/com/td/inv/wss/util/XMLConverters.java:[11,26] package com.rpmtec.current does not exist
[ERROR] /D:/jenkins/workspace/CBAW/testP/WSW_Investment/src/main/java/com/td/inv/wss/util/XMLConverters.java:[15,38] cannot find symbol
  symbol:   class AbstractRequestMessageData_Type
  location: class com.td.inv.wss.util.XMLConverters
[ERROR] /D:/jenkins/workspace/CBAW/testP/WSW_Investment/src/main/java/com/td/inv/wss/util/XMLConverters.java:[26,23] cannot find symbol
  symbol:   class AbstractResponseMessageData_Type
  location: class com.td.inv.wss.util.XMLConverters
[ERROR] /D:/jenkins/workspace/CBAW/testP/WSW_Investment/src/main/java/com/td/inv/wss/util/UsTermRateItemComparator.java:[5,42] package com.rpmtec.current.UsTermRate_Type does not exist
[ERROR] /D:/jenkins/workspace/CBAW/testP/WSW_Investment/src/main/java/com/td/inv/wss/util/UsTermRateItemComparator.java:[7,61] cannot find symbol
  symbol: class UsTermRateItems
[ERROR] /D:/jenkins/workspace/CBAW/testP/WSW_Investment/src/main/java/com/td/inv/wss/util/UsTermRateItemComparator.java:[9,28] cannot find symbol
  symbol:   class UsTermRateItems
  location: class com.td.inv.wss.util.UsTermRateItemComparator
[ERROR] /D:/jenkins/workspace/CBAW/testP/WSW_Investment/src/main/java/com/td/inv/wss/util/UsTermRateItemComparator.java:[9,48] cannot find symbol
  symbol:   class UsTermRateItems
  location: class com.td.inv.wss.util.UsTermRateItemComparator
[ERROR] /D:/jenkins/workspace/CBAW/testP/WSW_Investment/src/main/java/com/td/inv/model/COIRQ.java:[9,40] package com.fasterxml.jackson.annotation does not exist
[ERROR] /D:/jenkins/workspace/CBAW/testP/WSW_Investment/src/main/java/com/td/inv/model/COIRQ.java:[10,26] package com.rpmtec.current does not exist
[ERROR] /D:/jenkins/workspace/CBAW/testP/WSW_Investment/src/main/java/com/td/inv/model/COIRQ.java:[11,26] package com.rpmtec.current does not exist
[ERROR] /D:/jenkins/workspace/CBAW/testP/WSW_Investment/src/main/java/com/td/inv/model/COIRQ.java:[12,26] package com.rpmtec.current does not exist
[ERROR] /D:/jenkins/workspace/CBAW/testP/WSW_Investment/src/main/java/com/td/inv/model/COIRQ.java:[13,26] package com.rpmtec.current does not exist
[ERROR] /D:/jenkins/workspace/CBAW/testP/WSW_Investment/src/main/java/com/td/inv/model/COIRQ.java:[14,42] package com.rpmtec.current.UsTermRate_Type does not exist
[ERROR] /D:/jenkins/workspace/CBAW/testP/WSW_Investment/src/main/java/com/td/inv/model/COIRQ.java:[19,2] cannot find symbol
  symbol: class JsonIgnoreProperties
[ERROR] /D:/jenkins/workspace/CBAW/testP/WSW_Investment/src/main/java/com/td/inv/model/COIRQ.java:[69,22] cannot find symbol
  symbol:   class ORCA_GETTERMHOLDINGRS_Type
  location: class com.td.inv.model.COIRQ
[ERROR] /D:/jenkins/workspace/CBAW/testP/WSW_Investment/src/main/java/com/td/inv/model/COIRQ.java:[69,66] cannot find symbol
  symbol:   class RPM_GETPLANACCOUNTOVERVIEWRS_Type
  location: class com.td.inv.model.COIRQ
[ERROR] /D:/jenkins/workspace/CBAW/testP/WSW_Investment/src/main/java/com/td/inv/model/COIRQ.java:[70,25] cannot find symbol
  symbol:   class ORCA_GETTERMINSTRUCTIONRS_Type
  location: class com.td.inv.model.COIRQ
[ERROR] /D:/jenkins/workspace/CBAW/testP/WSW_Investment/src/main/java/com/td/inv/wss/util/RPMInvoker.java:[5,26] package javax.ws.rs.client does not exist
[ERROR] /D:/jenkins/workspace/CBAW/testP/WSW_Investment/src/main/java/com/td/inv/wss/util/RPMInvoker.java:[6,26] package javax.ws.rs.client does not exist
[ERROR] /D:/jenkins/workspace/CBAW/testP/WSW_Investment/src/main/java/com/td/inv/wss/util/RPMInvoker.java:[7,26] package javax.ws.rs.client does not exist
[ERROR] /D:/jenkins/workspace/CBAW/testP/WSW_Investment/src/main/java/com/td/inv/wss/util/RPMInvoker.java:[8,26] package javax.ws.rs.client does not exist
[ERROR] /D:/jenkins/workspace/CBAW/testP/WSW_Investment/src/main/java/com/td/inv/wss/util/RPMInvoker.java:[9,24] package javax.ws.rs.core does not exist
[ERROR] /D:/jenkins/workspace/CBAW/testP/WSW_Investment/src/main/java/com/td/inv/wss/util/RPMInvoker.java:[15,26] package com.rpmtec.current does not exist
[ERROR] /D:/jenkins/workspace/CBAW/testP/WSW_Investment/src/main/java/com/td/inv/wss/util/RPMInvoker.java:[16,26] package com.rpmtec.current does not exist
[ERROR] /D:/jenkins/workspace/CBAW/testP/WSW_Investment/src/main/java/com/td/inv/wss/util/RPMInvoker.java:[23,57] cannot find symbol
  symbol:   class AbstractRequestMessageData_Type
  location: class com.td.inv.wss.util.RPMInvoker
[ERROR] /D:/jenkins/workspace/CBAW/testP/WSW_Investment/src/main/java/com/td/inv/wss/util/RPMInvoker.java:[24,41] cannot find symbol
  symbol:   class AbstractResponseMessageData_Type
  location: class com.td.inv.wss.util.RPMInvoker
[ERROR] /D:/jenkins/workspace/CBAW/testP/WSW_Investment/src/main/java/com/td/inv/wss/application/InvestmentAPI.java:[4,19] package javax.ws.rs does not exist
[ERROR] /D:/jenkins/workspace/CBAW/testP/WSW_Investment/src/main/java/com/td/inv/wss/application/InvestmentAPI.java:[5,24] package javax.ws.rs.core does not exist
[ERROR] /D:/jenkins/workspace/CBAW/testP/WSW_Investment/src/main/java/com/td/inv/wss/application/InvestmentAPI.java:[9,36] cannot find symbol
  symbol: class Application

这是我的父 POM:

.....
<modelVersion>4.0.0</modelVersion>
<groupId>group1</groupId>
<artifactId>group1-artifact</artifactId>
<version>1.0.1</version>
<packaging>pom</packaging>

<modules>
     <module>child1</module>
</modules>
.......

这是我的孩子 POM:

.....
<modelVersion>4.0.0</modelVersion>
<parent>
    <groupId>group1</groupId>
    <artifactId>group1-artifact</artifactId>
    <version>1.0.1</version>
    <relativePath>(full url.....)/jenkins-parent-pom//pom.xml</relativePath>
</parent>
<groupId>group1</groupId>
<artifactId>child1</artifactId>
<version>0.0.1</version>
<packaging>war</packaging>
......

这是我尝试从父 POM 继承子 POM 中的依赖项的方式:

<dependencyManagement>  
  <dependencies>
    <dependency>
      <groupId>group1</groupId>
      <artifactId>group1-artifact</artifactId>
      <version>1.0.1</version>
      <type>pom</type>
      <scope>import</scope>
    </dependency>
  </dependencies>
</dependencyManagement>

如果我将这些相同的依赖项放在子 POM 中,它会完美运行。我使用 clean install 进行安装,deploy 使用 jenkins 在 nexus 中进行部署。我正在使用 maven-3.3.9。在 jenkins 中,我从 git 阅读了两个不同的 maven 项目中的父子 pom。我想从父 POM 继承所有依赖项和插件。可能吗?

【问题讨论】:

【参考方案1】:

您应该在&lt;dependencies&gt; 部分下声明要继承的依赖项以实现此目的。 &lt;dependencyManagement&gt; 用于以后必须在需要时在特定子级的&lt;dependencies&gt; 中引用才能生效的定义。

更新:在声明每个子 pom 将继承的依赖项时要小心。很快你就会得到你并不真正需要的依赖,因为它们是在父级中声明的。正如其他评论者所提到的,&lt;dependencyManagement&gt; 可能是更好的选择,尽管它不是您最初想要的。

【讨论】:

你的意思是,在父 pom 中我应该在 标记中声明所有依赖项,而不是在 或子 pom 中?我已将所有依赖项放在父 pom 中的 标记中。有问题吗? 如果您的目标是继承所有子 pom 的特定依赖项,而不需要在每个子项中清除它们 - 那么是的,您应该在 &lt;dependencies&gt; 而不是 &lt;dependencyManagement&gt; 中声明它们。另一方面,在&lt;dependencyManagement&gt; 中声明的依赖项只能在您需要在子 pom 中使用时使用——您只需在该子的&lt;dependencies&gt; 中写入其组和工件。好处是其他属性(版本)只在父级中声明一次。 谢谢。是的,我的目标是继承对子 pom 的特定依赖项。只是为了确保,根据您的回复,我会将这些特定的依赖项放在父 pom 中的 (而不是 标记中),对吗? 以及如何通过子项目使用父项目的类? RE:评论“声明每个子 pom 将继承的依赖项时要小心。非常快..”请注意,@vempo 指的是不使用 的另一个选项但是,它是重要的是要注意两者都有其有效的用例,...我希望 Maven 使用不同/更好的名称来识别这两种机制。【参考方案2】:

事实上,你有两种方法来处理这个问题。

    要么在 &lt;dependencyManagement /&gt; 节点下的父 pom 中考虑依赖关系,在每个需要它的子节点中,将依赖关系添加到 &lt;dependencies /&gt; 节点中。您可以选择不设置依赖的版本。 或者你在&lt;dependencies /&gt;节点的父pom中声明依赖,每个子都会从依赖中受益。

例如,如果你在父 pom 中声明:

<dependencies>
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
        <version>1.7.21</version>
    </dependency>
</dependencies>
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-simple</artifactId>
            <version>1.7.21</version>
            <scope>runtime</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

那么slf4j-api 将成为所有子级的依赖项。但是,如果需要,您必须在孩子的 pom 中添加对 slf4j-simple 的依赖:

<dependencies>
    <dependency>
        <group>org.slf4j</group>
        <artifactId>slf4j-simple</artifactId>
    </dependency>
</dependencies>

对于插件,它的工作原理相同,但使用 &lt;pluginManagement /&gt;&lt;plugins /&gt; 节点。所有配置都可以在父 pom 的插件定义中进行,您只需在子 pom 的 &lt;build /&gt; 部分中声明插件即可。

【讨论】:

谢谢。但是如果不在节点的子pom中添加依赖,不设置依赖的版本,我是不可能从父pom继承依赖的,对吧? 我更新了我的答案,因为它不准确。事实证明,如果将依赖项添加到父 pom 的 &lt;dependencies /&gt; 节点中,则不需要在子 pom 中添加依赖项。这是你的选择。 虽然你当然可以这样做,但将&lt;dependencies /&gt; 放在&lt;dependencyManagement /&gt; 之外的父pom 中并不是一个好主意。您的所有子模块将始终继承所有这些依赖项。任何其他可能使用您的模块之一的项目也将暂时获得所有这些 dep 并且可能发生冲突或更糟,特别是如果该子模块不使用所有这些。 @ArthurNoseda 的原始解决方案是最好的。 以及如何通过子项目使用父项目的类?【参考方案3】:

下面是如何使用父子pom的示例。

父pom如下:

.....
<modelVersion>4.0.0</modelVersion>
<groupId>group1</groupId>
<artifactId>group1-artifact</artifactId>
<version>1.0.1</version>
<packaging>pom</packaging>

<modules>
     <module>child1</module>
     // add more childs here
</modules>

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-simple</artifactId>
            <version>1.7.21</version>
        </dependency>
        <dependency>
            <groupId>org.abc</groupId>
            <artifactId>xyz</artifactId>
            <version>1.0.0</version>
        </dependency>
    </dependencies>
</dependencyManagement>
.......

如果你在dependencyManagement 标签中指定了一个依赖,它仅仅意​​味着你让这个jar 可用于子pom。此时它不会实际下载 jar。子 pom 必须提供 groupIdartifactId 明确 下载并使用 jar 编译其类。 注意:您不必在子 pom 中包含依赖项的版本

子pom如下:

.....
<modelVersion>4.0.0</modelVersion>

<parent>            // this is how you will inherit from parent pom
    <groupId>group1</groupId>
    <artifactId>group1-artifact</artifactId>
    <version>1.0.1</version>
</parent>

<groupId>child1</groupId>

    <dependencies>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-simple</artifactId>
            <scope>runtime</scope>
            // no version needed as it would inherit from the parent pom
        </dependency>
        <dependency>
            <groupId>org.abc</groupId>
            <artifactId>xyz</artifactId>
            // no version needed as it would inherit from the parent pom
        </dependency>
    </dependencies>

.......

最好将所有子级的公共依赖项放在父级 pom 的 dependencyManagement 标记中。这样您就可以从一个地方管理这些依赖项的版本。

【讨论】:

以及如何通过子项目使用父项目的类? 不是pom类型的父项目吗?里面不应该有任何类。 是的,@ArthurNoseda 是正确的。您的父 pom 通常是 pom 类型,而不是 jar 或 war。理想情况下,父 pom 不会有任何代码。它的主要目的是充当所有子 pom 的聚合器。 如果我希望在子 pom 中使用时在依赖项中发生排除,我可以从父项中排除 ... 吗? 如果您希望将 jar 从任何特定子项中排除,那么最好将排除项添加到该子 pom.xml 中。然而,如果您希望将 jar 从所有子 pom 中排除,则可以在父 pom 中添加排除。【参考方案4】:

父 pom.xml

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
         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>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.4.RELEASE</version>
    </parent>

    <groupId>com.ll</groupId>
    <artifactId>parent-module</artifactId>
    <packaging>pom</packaging>
    <version>1.0-SNAPSHOT</version>

    <!-- child will inherit all content -->
    <dependencies>
        <dependency>
            <groupId>com.google.protobuf</groupId>
            <artifactId>protobuf-java</artifactId>
            <version>3.11.0</version>
        </dependency>
    </dependencies>

    <!-- child will inherit only version-->
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.apache.zookeeper</groupId>
                <artifactId>zookeeper</artifactId>
                <version>3.5.7</version>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <modules>
        <module>sub-module1</module>
        <module>sub-module2</module>
    </modules>
</project>

子 pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
         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>
    <parent>
        <groupId>com.ll</groupId>
        <artifactId>parent-module</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>

    <groupId>com.ll</groupId>
    <artifactId>sub-module1</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>

    <dependencies>
        <dependency>
            <groupId>org.apache.zookeeper</groupId>
            <artifactId>zookeeper</artifactId>
        </dependency>
    </dependencies>
</project>
1.child will use zookeeper:3.5.7, the version is from parent pom.xml <dependencyManagement>:<dependencies>:<dependency>. 

2.child will use protobuf-java:3.11.o, it is from parent pom.xml <dependencies>:<dependency>.

【讨论】:

【参考方案5】:

&lt;dependencyManagement&gt; 中添加的任何内容都会自动添加到孩子的 pom 中。唯一需要注意的是,在孩子的 pom 中,我们不需要显式添加版本,否则这将是仅可用于子模块的其他依赖项。

parent_pom.xml

    <dependencyManagement>
      <dependencies>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.20</version>
        </dependency>
     </dependencies>
  </dependencyManagement>

child_pom.xml

        <dependency>
          <groupId>org.projectlombok</groupId>
          <artifactId>lombok</artifactId>
        </dependency>

【讨论】:

以上是关于如何从父pom继承依赖到子pom的主要内容,如果未能解决你的问题,请参考以下文章

无法将Spring Boot依赖项从父模块导入子模块

maven如何继承父工程的依赖关系

maven继承与聚合

pom.xml的继承聚合与依赖

子 pom 可以从自定义父 pom 的 spring-boot-starter-parent 继承插件管理和依赖管理吗?

maven父子工程的pom.xml继承