Maven的 parent 解决配置继承,modules 解决一起构建。一个项目可以同时承担两种角色,但“某项目是父项目”本身,不意味着对它执行package就会构建所有继承者。

用一个最小目录区分两条关系

假设有以下布局:

demo/
  pom.xml
  app/
    pom.xml

根POM同时提供共享属性并列出模块:

<project xmlns="http://maven.apache.org/POM/4.0.0">
  <modelVersion>4.0.0</modelVersion>
  <groupId>example</groupId>
  <artifactId>demo-parent</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>pom</packaging>
  <properties>
    <demo.message>shared-value</demo.message>
  </properties>
  <modules>
    <module>app</module>
  </modules>
</project>

app/pom.xml 指定父POM:

<project xmlns="http://maven.apache.org/POM/4.0.0">
  <modelVersion>4.0.0</modelVersion>
  <parent>
    <groupId>example</groupId>
    <artifactId>demo-parent</artifactId>
    <version>1.0-SNAPSHOT</version>
    <relativePath>../pom.xml</relativePath>
  </parent>
  <artifactId>app</artifactId>
</project>

这个结构中,app从父POM继承groupId、version及共享属性;根POM通过modules把app纳入聚合。两条关系恰好重合,但并不必然重合。Maven POM:继承与聚合

改一处,就能看出它们不相同

如果从根POM移除modules,app仍可以继承它,但从根项目启动的构建不会自动搜索磁盘上所有把它当parent的项目。

反过来,聚合POM也可以列出不以自己为parent的模块。聚合选择谁进入同次构建;继承决定每个项目的有效配置,不能互相替代。

另外,“构建所有模块”不是把所有子模块内容塞进一个JAR。各模块按各自packaging产生产物;聚合根的 pom 类型也不是可执行应用包。

构建入口决定这次会做什么

在根目录执行 mvn package 与进入app目录执行同一目标,项目集合可能不同。-pl、-am 等选择项还会影响reactor范围;依赖关系用于安排顺序,modules列表顺序不是唯一依据。Maven reactor说明

排查时分别核对父坐标、relativePath、模块路径、有效POM和Reactor Build Order。不要仅凭看到parent标签,就断言所有兄弟模块都已打包或发布。