ChatGPT解决这个技术问题 Extra ChatGPT

Maven 父 pom 与模块 pom

似乎有几种方法可以在多项目构建中构建父 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 中更易于管理,如果子模块是 Eclipse 中的单独项目,则第一个和第三个示例中的根 pom.xml 将难以包含。

P
Pascal Thivent

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

如果答案是肯定的(问题或评论中提到的大多数项目都是这种情况),那么父 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 作为其<parent>,你将如何处理版本#但是一些其他项目的父pom?我们将为此类项目的工件获得哪些版本#(这些项目的 <parent> 部分中工件的版本# 或将这些项目列为模块的项目的版本#)? stackoverflow.com/questions/25918593/…
c
cetnar

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

“公司”父 pom - 这个 pom 包含您公司的特定信息和配置,这些信息和配置继承了每个 pom,不需要复制。这些信息是: 存储库 分发管理部分 常用插件配置(如 maven-compiler-plugin 源和目标版本) 组织、开发人员等 准备这个父 pom 需要小心,因为您公司的所有 pom 都将从它继承,所以这个 pom 必须成熟稳定(发布一个父 pom 版本不应该影响发布您公司所有的项目!)

存储库

分销管理科

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

组织、开发人员等

第二种父 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项目的构建。我对吗 ?
b
bmargulies

独立父级是在其他非耦合组件之间共享配置和选项的最佳实践。 Apache 有一个父 pom 项目来共享法律声明和一些常见的打包选项。如果您的顶级项目中有实际工作,例如聚合 javadoc 或打包发布,那么您将在完成该工作所需的设置与您希望通过父级共享的设置之间产生冲突。仅父项目可以避免这种情况。一个常见的模式(暂时忽略#1)是让项目代码使用父项目作为其父项目,并让它使用顶级作为父项目。这允许所有人共享核心内容,但避免了#2中描述的问题。如果父结构与目录结构不同,站点插件会变得非常混乱。如果你想建立一个聚合网站,你需要做一些摆弄来解决这个问题。 Apache CXF 是 #2 中的模式示例。


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

第三种方法有一个小问题。由于聚合 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)。

几种解决方案是可能的:

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