【问题标题】:Differences between a multi-module project and a parent project多模块项目和父项目的区别
【发布时间】:2018-01-13 21:54:24
【问题描述】:

在 Maven 的多模块项目中,我们有一个父 pom,其模块在 <modules> 标签中定义,在每个模块中,我们定义父 pom 是哪个。

  • 为什么是这种双向定义?

  • 为什么不在模块的父部分定义它们之间的关系

  • 如果模块总是绑定到一个父级,我应该如何重用它们?

【问题讨论】:

    标签: java maven maven-module


    【解决方案1】:

    为什么是这种双向定义?

    这不是强制性的。这是一种设计选择。

    为什么不在父级中定义?

    如果你只在父pom的modules标签中定义它们,你只会使用Maven的reactor/aggregation特性。

    1) 聚合(超级聚合器项目中的<modules> 声明)主要提供以下功能:

    • 收集所有可用的模块来构建
    • 按照正确的构建顺序对项目进行排序
    • 按顺序构建选定的项目

    通过在父 pom 中声明要聚合的模块来启用聚合模块:

    <modules>
        <module>my-child</module>
        <module>my-other-child</module>
    </modules>
    

    但聚合不提供继承。

    2)项目继承(子模块中的&lt;parent&gt;声明)提供了从父声明到子模块的多个事物的继承:

    从实际文档来看,父 POM 中的大多数元素都由其子代继承:

    • groupId
    • version
    • description
    • url
    • inceptionYear
    • organization
    • licenses
    • developers
    • contributors
    • mailingLists
    • scm
    • issueManagement
    • ciManagement
    • properties
    • dependencyManagement
    • dependencies
    • repositories
    • pluginRepositories
    • build
    • plugin executions with matching ids
    • plugin configuration
    • reporting
    • profiles

    通过在子 pom 中声明父工件来启用继承:

    <parent>
        <groupId>my-group</groupId>
        <artifactId>my-parent</artifactId>
        <version>1.0.0</version>
    </parent>
    
    <!-- You can note that groupId and version are not filled for the current project.
     These are optional as inherited from the parent -->
    <artifactId>my-artifact</artifactId>
    

    实际上,您可以使用项目继承、项目组合,或者两者都不使用。

    这确实是一个设计选择,应该根据项目和他们的需求之间的关系来做。

    这两个功能可以参考this interesting point on the Maven documentation

    项目继承与项目聚合

    如果您有多个 Maven 项目,并且它们都有相似的 配置,您可以通过拉出那些来重构您的项目 类似的配置并制作父项目。因此,你所拥有的一切 要做的是让您的 Maven 项目继承该父项目,并且 然后这些配置将应用于所有这些。

    如果您有一组正在构建或处理的项目 一起,您可以创建一个父项目并拥有该父项目 将这些项目声明为其模块。通过这样做,你只需要 构建父级,其余的将随之而来。

    当然,您可以同时拥有项目继承和项目 聚合。意思是,你可以让你的模块指定一个父级 项目,同时,让该父项目指定那些 Maven 项目作为其模块。

    用一个例子来说明。

    这里是一个多模块项目的父 pom.xml。

    <!-- PARENT POM -->
    <groupId>com.example</groupId>
    <artifactId>parent-demo</artifactId>
    <version>1.0.0-SNAPSHOT</version>
    <packaging>pom</packaging>
    
    <modules>
        <module>child-module</module>
    </modules>
    

    这是 Child Pom。

    <!-- CHILD POM -->
    <parent>
        <groupId>com.example</groupId>
        <artifactId>parent-demo</artifactId>
        <version>1.0.0-SNAPSHOT</version>
    </parent>
    <artifactId>chile-module</artifactId>
    

    这里,child-module 继承 parent-demo,但 parent-demo 不使用任何继承。

    如果你想,你的parent-demo 也使用继承,你可以像下面这样配置你的parent-demo

    <!-- PARENT POM -->
    <parent>
        <groupId>com.example</groupId>
        <artifactId>parent-deps</artifactId>
        <version>1.0.0-SNAPSHOT</version>
        <relativePath>../parent-deps</relativePath>
    </parent>
    <artifactId>parent-demo</artifactId>
    <packaging>pom</packaging>
    
    <modules>
        <module>child-module</module>
    </modules>
    

    现在,您的parent-demo 也继承了parent-deps 的配置,这些配置也被级联到child-module(除非parent-demo 决定覆盖它们)。

    【讨论】:

    • 太好了,现在一切都说得通了,我将使用项目聚合。
    • 不客气。有趣的问题。我进行了编辑以使我的答案更完整。
    • 直到这一刻,我一直在寻找答案并找到了它。这就是 maven 中子模块和父模块的区别。问题的标题应该更具体地描述这一点。也许maven中继承和聚合之间的区别。感谢 davidxxx 提供这个答案。
    • @Anddo 感谢您的反馈。标题可以改进是对的。问题是您建议的另一篇帖子的标题很接近(stackoverflow.com/questions/17482320/…)我更新了一个也特定于 maven 的变体。
    • 很好的解释!
    【解决方案2】:

    因为当你构建一些子模块时,它现在应该有一些元信息,例如依赖版本,并且将这些依赖项放入父 pom dependencyManagement 通常是更好的做法,因为我会让所有子模块都使用相同的库版本。还有其他可能有用的元信息,例如properties

    所以,总而言之,当您构建特定的子模块时,maven 应该知道您通常希望在父 pom 中设置的一些信息。

    我相信这可能有更多原因,但这对我来说是最明显的。

    如果你想在我看来重用模块,那么你需要将这些模块作为一个库,并通过dependency标签将它们添加为一个库。

    【讨论】:

    • 简单来说:parent 用于版本、依赖项、常用插件配置,而模块定义要构建的项目。它们可以不同。它通常对大型项目很有用。
    猜你喜欢
    • 2014-03-28
    • 1970-01-01
    • 2015-04-02
    • 2023-03-25
    • 2017-07-30
    • 1970-01-01
    • 2019-04-18
    • 2012-08-29
    • 1970-01-01
    相关资源
    最近更新 更多