【问题标题】:Maven parent pom vs modules pomMaven 父 pom 与模块 pom
【发布时间】:2010-12-31 19:44:54
【问题描述】:

似乎有几种方法可以在多项目构建中构建父 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 如何处理您如何设置多项目(可能是一个巨大的问题,如果有人被如何设置多项目构建所吸引,那就更重要了)?

编辑:每个子项目都有自己的 pom.xml,为了保持简洁,我把它省略了。

【问题讨论】:

  • 每个模块都有自己的 pom 吗?我的项目有一个父 pom,但每个模块也有一个 pom。 (也许是你描述的第四种方式)
  • 啊,是的,我会编辑和更新。每个子模块也有自己的 pom。
  • 作为一个更新,我可以看到第二个选项的一个优点是它更容易在 Eclipse 中管理,如果第一个和第三个示例中的根 pom.xml 很难包含子模块是 Eclipse 中的独立项目。

标签: java maven-2 build-process


【解决方案1】:

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

如果答案是(问题或 cmets 中提到的大多数项目都是这种情况),那么父 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 是一种“假”pom:它从未发布过,它不包含真实版本,因为此文件从未发布过,它仅包含模块列表。使用此文件,结帐将产生此结构(模式 #3):

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

这个“hack”允许在结帐后从根目录启动反应堆构建,让事情变得更加方便。实际上,这就是我喜欢为 大型构建 设置 maven 项目和 VCS 存储库的方式:它可以正常工作,可以很好地扩展,它提供了您可能需要的所有灵活性。

如果答案是(回到最初的问题),那么我认为你可以接受模式#1(做可能可行的最简单的事情)。

现在,关于奖金问题:

  • 哪里是定义各种共享配置的最佳位置,如源代码控制、部署目录、常用插件等。(我假设是父级,但我经常被这个咬到,它们最终出现在每个项目而不是普通项目)。

老实说,我不知道如何不在这里给出一般性的答案(例如“使用您认为有意义的水平来使事物相互化”)。无论如何,子 pom 总是可以覆盖继承的设置。

  • maven-release 插件、hudson 和 nexus 如何处理您如何设置多项目(可能是一个巨大的问题,如果有人被如何设置多项目构建所吸引,那就更重要了)?

我使用的设置效果很好,没有什么特别要提的。

实际上,我想知道 maven-release-plugin 如何处理模式 #1(尤其是 <parent> 部分,因为在发布时您不能拥有 SNAPSHOT 依赖项)。这听起来像是先有鸡还是先有蛋的问题,但我只是不记得它是否有效并且懒得测试它。

【讨论】:

  • 这很好,我可以看到它是如何扩展的。 svn:externals 回答了我对它很麻烦的担忧。
  • @jamie 很高兴你觉得它有帮助。
  • 您能否详细说明如何使“黑客”发挥作用?我有主干项目,并预计您将 -pl 选项与“启动反应堆构建”作为目标,但这在对结构进行发布时会出现问题,因为此选项也不会从根级别的构建传递我可以将它放在发布插件的 选项中吗?因此 release:perform 失败,因为它试图在根级 pom 上工作......
  • svn:externals hack 是我很久以来见过的最有用的 svn hack。对于在同一存储库中具有每个项目分支的项目非常有用。
  • 嗨 Pascal,如果模块部分中提到的项目不使用 parent-pom 作为其 而是使用其他项目的父级 pom,您将如何处理版本号?我们将为此类项目的工件获得哪些版本(这些项目的 部分中工件的版本#或将这些项目列为模块的项目的版本#)? stackoverflow.com/questions/25918593/…
【解决方案2】:

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

  • "company" 父 pom - 这个 pom 包含您公司的特定信息和配置,这些信息和配置继承了每个 pom,不需要复制。这些信息是:

    • 存储库
    • 分销管理部分
    • 常用插件配置(如 maven-compiler-plugin 源和目标版本)
    • 组织、开发人员等

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

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

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

Mutliprojects 具有树结构 - 所以你不会被向下箭头到父 pom 的一级。尝试找到适合您需求的项目结构 - 一个经典示例是如何分发多模块项目

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

几个额外的问题:

  • 哪里是定义各种共享配置的最佳位置,如源代码控制、部署目录、常用插件等。(我假设是父级,但我经常被这个咬到,它们最终出现在每个项目而不是普通项目)。

此配置必须明智地拆分为“公司”父 pom 和项目父 pom。与您的所有项目相关的事情都转到“公司”父级,而与当前项目相关的则转到项目一个。

  • maven-release 插件、hudson 和 nexus 如何处理您如何设置多项目(可能是一个巨大的问题,如果有人被如何设置多项目构建所吸引,那就更重要了)?

必须先发布公司父 pom。对于多项目标准规则适用。 CI服务器需要知道一切才能正确构建项目。

【讨论】:

  • 这样就有两种类型的父项目/pom。一个没有 声明。这是用于继承的。还有一个带有 声明的父项目。这是子模块不继承的一个,它只是为了管理hold项目的构建。我说的对吗?
【解决方案3】:
  1. 独立的父级是在其他未耦合的组件之间共享配置和选项的最佳实践。 Apache 有一个父 pom 项目来共享法律声明和一些常见的打包选项。

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

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

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

【讨论】:

  • 我看过 ibilio 并且很多项目似乎更喜欢“独立”的父 pom。 Hibernate、ActiveMQ、Jetty、XStream 等。这表明它是事实上的机制。
  • 独立父级的另一个缺点似乎是 maven 发布插件似乎希望父级在发布之前被固定到一个版本。可能不是什么大问题,因为父母不应该改变太多。
【解决方案4】:

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

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

有几种可能的解决方案:

  1. 将插件部署到 Maven 中心(并非总是可行)。
  2. 在所有聚合 POM 中指定存储库部分(违反 DRY 原则)。
  3. 在 settings.xml 中配置此内部存储库(在 ~/.m2/settings.xml 的本地设置或 /conf/settings.xml 的全局设置中)。没有这些 settings.xml 会导致构建失败(对于不应该在公司外部构建的大型内部项目可能没问题)。
  4. 在您的聚合 POM 中使用具有存储库设置的父级(可能是太多的父级 POM?)。

【讨论】:

    猜你喜欢
    • 2013-02-23
    • 2020-04-26
    • 1970-01-01
    • 2012-04-27
    • 1970-01-01
    • 1970-01-01
    • 2020-06-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多