Maven父母pom vs模块pom

Jam*_*dle 279 java build-process maven-2

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

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

myproject/
  myproject-core/
  myproject-api/
  myproject-app/
  pom.xml
Run Code Online (Sandbox Code Playgroud)

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

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

myproject/
  mypoject-parent/
    pom.xml
  myproject-core/
  myproject-api/
  myproject-app/
Run Code Online (Sandbox Code Playgroud)

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

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

myproject/
  mypoject-parent/
    pom.xml
  myproject-core/
  myproject-api/
  myproject-app/
  pom.xml
Run Code Online (Sandbox Code Playgroud)

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

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

一些奖金问题:

  • 在源代码控制,部署目录,常见插件等中定义各种共享配置的最佳位置在哪里(我假设父母,但我经常被这种情况所困扰,他们最终在每个项目中而不是常见的一个).
  • maven-release插件,hudson和nexus如何处理你如何设置你的多项目(可能是一个巨大的问题,如果有人因为如何设置多项目构建而被抓住了,那就更多了?)

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

Pas*_*ent 164

在我看来,要回答这个问题,你需要考虑项目生命周期和版本控制.换句话说,父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
Run Code Online (Sandbox Code Playgroud)

这使得结账有点痛苦,并且常用的方法是使用它svn:externals.例如,添加trunks目录:

root
|-- parent-pom
|   |-- branches
|   |-- tags
|   `-- trunk
|       `-- pom.xml
|-- projectA
|   |-- branches
|   |-- tags
|   `-- trunk
|       |-- module1
|       |   `-- pom.xml
|       |-- moduleN
|       |   `-- pom.xml
|       `-- pom.xml
`-- trunks
Run Code Online (Sandbox Code Playgroud)

具有以下外部定义:

parent-pom http://host/svn/parent-pom/trunk
projectA http://host/svn/projectA/trunk
Run Code Online (Sandbox Code Playgroud)

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

root/
  parent-pom/
    pom.xml
  projectA/
Run Code Online (Sandbox Code Playgroud)

或者,您甚至可以pom.xmltrunks目录中添加:

root
|-- parent-pom
|   |-- branches
|   |-- tags
|   `-- trunk
|       `-- pom.xml
|-- projectA
|   |-- branches
|   |-- tags
|   `-- trunk
|       |-- module1
|       |   `-- pom.xml
|       |-- moduleN
|       |   `-- pom.xml
|       `-- pom.xml
`-- trunks
    `-- pom.xml
Run Code Online (Sandbox Code Playgroud)

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

root/
  parent-pom/
    pom.xml
  projectA/
  pom.xml
Run Code Online (Sandbox Code Playgroud)

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

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

现在,关于奖金问题:

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

老实说,我不知道如何在这里不给出一般性的答案(比如"使用你认为将事物分开是有意义的水平").无论如何,子poms总是可以覆盖继承的设置.

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

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

实际上,我想知道maven-release-plugin如何处理模式#1(特别是对于该<parent>部分,因为在发布时你不能拥有SNAPSHOT依赖项).这听起来像鸡或鸡蛋的问题,但我不记得它是否有效,而且懒得测试它.


cet*_*nar 34

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

  • "公司"父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
Run Code Online (Sandbox Code Playgroud)

一些奖金问题:

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

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

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

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


bma*_*ies 22

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

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

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

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

  5. Apache CXF就是#2中的模式的一个例子.

  • 我看过ibilio,许多项目似乎更喜欢"独立"的父母pom.Hibernate,ActiveMQ,Jetty,XStream等.这表明它是事实上的机制. (2认同)
  • 独立父级的另一个缺点似乎是maven发布插件似乎希望在发布之前将父级固定到某个版本.可能不是很大的问题,因为父母不应该改变太多. (2认同)

Iva*_*rov 9

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

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

有几种解决方案可行:

  1. 将插件部署到Maven Central(并非总是可行).
  2. 在所有聚合POM中指定存储库部分(中断DRY原则).
  3. 在settings.xml中配置此内部存储库(在〜/ .m2/settings.xml的本地设置中或在/conf/settings.xml的全局设置中).如果没有那些settings.xml,构建就会失败(对于那些永远不应该在公司外部构建的大型内部项目来说可能没问题).
  4. 在聚合POM中使用具有存储库设置的父级(可能是太多的父POM?).