首页 文章

Maven父母pom vs模块pom

提问于
浏览
266

在多项目构建中似乎有几种方法来构建父pom,我想知道是否有人对每种方式的优点/缺点有任何想法 .

拥有父pom的最简单方法是将它放在项目的根目录中,即

myproject/
  myproject-core/
  myproject-api/
  myproject-app/
  pom.xml

其中pom.xml既是父项目又是-core -api和-app模块

下一个方法是将父项分离到它自己的子目录中,如中所示

myproject/
  mypoject-parent/
    pom.xml
  myproject-core/
  myproject-api/
  myproject-app/

父pom仍然包含模块,但它们是相对的,例如../myproject-core

最后,有一个选项,模块定义和父项分开,如

myproject/
  mypoject-parent/
    pom.xml
  myproject-core/
  myproject-api/
  myproject-app/
  pom.xml

父pom包含任何“共享”配置(dependencyManagement,属性等),myproject / pom.xml包含模块列表 .

目的是可扩展到大规模构建,因此应该可以扩展到大量项目和工件 .

一些奖金问题:

  • 在源控件,部署目录,常见插件等中定义各种共享配置的最佳位置在哪里(我经常被这种情况所困扰,并且它们最终出现在每个项目中而不是常见的项目中) .

  • maven-release插件,hudson和nexus如何处理你如何设置你的多项目(可能是一个巨大的问题,如果有人因为如何 Build 多项目构建而被 grab 了,那就更多了?)

编辑:每个子项目都有自己的pom.xml,我把它留了下来以保持简洁 .

4 回答

  • 32

    在我看来,要回答这个问题,你需要考虑项目生命周期和版本控制 . 换句话说,父pom是否有自己的生命周期,即它是否可以与其他模块分开发布?

    如果答案是 yes (这是问题或评论中提到的大多数项目的情况),那么父pom需要从VCS和Maven的角度来看他自己的模块,你最终会在VCS级别使用类似的东西:

    root
    |-- parent-pom
    |   |-- branches
    |   |-- tags
    |   `-- trunk
    |       `-- pom.xml
    `-- projectA
        |-- branches
        |-- tags
        `-- trunk
            |-- module1
            |   `-- pom.xml
            |-- moduleN
            |   `-- pom.xml
            `-- pom.xml
    

    这使得结账有点痛苦,处理这种情况的常用方法是使用 svn:externals . 例如,添加 trunks 目录:

    root
    |-- parent-pom
    |   |-- branches
    |   |-- tags
    |   `-- trunk
    |       `-- pom.xml
    |-- projectA
    |   |-- branches
    |   |-- tags
    |   `-- trunk
    |       |-- module1
    |       |   `-- pom.xml
    |       |-- moduleN
    |       |   `-- pom.xml
    |       `-- pom.xml
    `-- trunks
    

    具有以下外部定义:

    parent-pom http://host/svn/parent-pom/trunk
    projectA http://host/svn/projectA/trunk
    

    结账 trunks 将导致以下本地结构(模式#2):

    root/
      parent-pom/
        pom.xml
      projectA/
    

    或者,您甚至可以在 trunks 目录中添加 pom.xml

    root
    |-- parent-pom
    |   |-- branches
    |   |-- tags
    |   `-- trunk
    |       `-- pom.xml
    |-- projectA
    |   |-- branches
    |   |-- tags
    |   `-- trunk
    |       |-- module1
    |       |   `-- pom.xml
    |       |-- moduleN
    |       |   `-- pom.xml
    |       `-- pom.xml
    `-- trunks
        `-- pom.xml
    

    这个 pom.xml 是一种"fake" pom:它永远不会发布,它不包含真正的版本,因为这个文件永远不会发布,它只包含一个模块列表 . 使用此文件,结帐将导致此结构(模式#3):

    root/
      parent-pom/
        pom.xml
      projectA/
      pom.xml
    

    这个"hack"允许在结账后从根启动反应堆构建,并使事情变得更加方便 . 实际上,这就是我喜欢为 large builds 设置maven项目和VCS存储库的方式:它只是工作,它可以很好地扩展,它提供了您可能需要的所有灵活性 .

    如果答案是 no (回到最初的问题),那么我认为你可以使用模式#1(做最简单的事情可能有效) .

    现在,关于奖金问题:

    在源控件,部署目录,常见插件等中定义各种共享配置的最佳位置在哪里(我假设父母,但我经常被这种情况所困扰,他们最终在每个项目中结束了比一般的) .

    老实说,我不知道如何在这里不给出一般性的答案(比如“使用你认为有用的水平来实现共同化”) . 无论如何,子poms总是可以覆盖继承的设置 .

    maven-release插件,hudson和nexus如何处理你如何设置你的多项目(可能是一个巨大的问题,如果有人因为如何 Build 多项目构建而被 grab 了,那就更多了?)

    我使用的设置很好,没什么特别值得一提的 .

    实际上,我想知道maven-release-plugin如何处理模式#1(尤其是 <parent> 部分,因为你可以记住它是否有效并且懒得测试它 .

  • 22

    根据我的经验和Maven最佳实践,有两种“父母poms”

    • “company”父pom - 此pom包含公司特定的信息和配置,它们继承每个pom而不需要复制 . 这些信息是:

    • 存储库

    • 分发管理部分

    • 常见的插件配置(如maven-compiler-plugin源和目标版本)

    • 组织,开发商等

    准备这个父pom需要谨慎,因为你所有的公司poms都将继承它,所以这个pom必须是成熟和稳定的(发布一个父pom的版本不应该影响你发布所有的公司项目!)

    • 第二种父pom是一个多模块父类 . 我更喜欢你的第一个解决方案 - 这是多模块项目的默认maven约定,经常表示VCS代码结构

    目的是扩展到大规模构建,因此应该可以扩展到大量项目和工件 .

    Mutliprojects具有树木的结构 - 所以你不会向下到一级父母pom . 尝试找到适合您需求的项目结构 - 一个典型的例子是如何解决mutimodule项目

    distibution/
    documentation/
    myproject/
      myproject-core/
      myproject-api/
      myproject-app/
      pom.xml
    pom.xml
    

    一些奖励问题:在源代码控制,部署目录,常见插件等中定义各种共享配置的最佳位置在哪里(我假设是父母,但我经常被这种情况所困扰,他们已经结束了在每个项目而不是常见的项目中 .

    必须明智地将此配置拆分为“公司”父pom和项目父pom . 与你所有项目相关的事情都转到“公司”的父母,这与当前项目有关,转到项目一 .

    maven-release插件,hudson和nexus如何处理你如何设置你的多项目(可能是一个巨大的问题,如果有人因为如何 Build 多项目构建而被 grab 了,那就更多了?)

    公司父母pom必须先发布 . 对于多项目,适用标准规则 . CI服务器需要知道所有正确构建项目 .

  • 9
    • 独立父级是在其他未耦合组件之间共享配置和选项的最佳实践 . Apache有一个父pom项目来分享法律声明和一些常见的包装选项 .

    • 如果您的顶级项目中有实际工作,例如聚合javadoc或打包版本,那么执行该工作所需的设置与您希望通过父项共享的设置之间会有冲突 . 仅限父项目可以避免这种情况 .

    • 一个常见的模式(暂时忽略#1)是让代码项目使用父项目作为其父项目,并让它使用顶层作为父项目 . 这允许所有人共享核心内容,但避免了#2中描述的问题 .

    • 如果父结构与目录结构不同,则网站插件会变得非常混乱 . 如果你想 Build 一个聚合网站,你需要做一些摆弄来解决这个问题 .

    • Apache CXF是#2中的模式的示例 .

  • 159

    第三种方法有一个小问题 . 由于聚合POM(myproject / pom.xml)通常根本没有父级,因此它们不共享配置 . 这意味着所有这些聚合POM将只有默认存储库 .

    如果你只使用Central的插件,这不是问题,但是,如果你使用内部存储库中的插件:目标格式运行插件,这将失败 . 例如,您可以拥有 foo-maven-plugin ,其中groupId为 org.example ,提供目标 generate-foo . 如果您尝试使用 mvn org.example:foo-maven-plugin:generate-foo 之类的命令从项目根目录运行它,它将无法在聚合模块上运行(请参阅compatibility note) .

    有几种解决方案可行:

    • 将插件部署到Maven Central(并非总是可行) .

    • 在所有聚合POM中指定存储库部分(中断DRY原则) .

    • 在settings.xml中配置此内部存储库(在〜/ .m2 / settings.xml的本地设置中或在/conf/settings.xml的全局设置中) . 如果没有那些settings.xml,将使构建失败(对于绝对不应该在公司外部构建的大型内部项目可能没问题) .

    • 在聚合POM中使用具有存储库设置的父级(父POM可能太多?) .

相关问题