先说结论:这不是 IDEA 的 bug,也不完全是 Maven 配置写错,而是大多数人对“父项目打包”这个动作的理解和 Maven 实际行为之间差了层窗户纸。我见过不少同事在 IDEA 里对父工程右键,点Maven > Lifecycle > package,跑完发现 target 目录里只有一个孤零零的父包,子模块一个都没动,第一反应就是“IDEA 是不是出问题了”。这篇文章就专门把这层窗户纸捅破,讲清楚父项目打包时子项目的设置逻辑,顺带把 Maven 多模块工程在 IDEA 里正确打包的姿势一起给出来。
这里说的“父项目打包”,实际指的是 Maven 聚合工程里的父 POM。你在 IDEA 里看到的父子结构,本质上是 Maven 的<parent>继承和<modules>聚合两个概念叠加在一起。如果你对这两个概念没有任何区分,那后面所有排查都会绕圈子。这篇文章会从最核心的 packaging 和 modules 配置讲起,再带你把 IDEA 里的操作流程走一遍,最后把最常见的坑和排查思路全部列出来。无论你是刚接触 Maven 多模块工程的新手,还是已经在用 Spring Cloud、Dubbo 这类多模块项目的开发者,都值得花几分钟看完。
1. 先搞清楚:Maven 的“父项目打包”到底是个什么动作
1.1 聚合与继承,两个容易混的概念
很多人在父 POM 里看到<parent>和<modules>两个标签,下意识觉得是同一个东西,其实完全不是。
继承解决的是“子工程和父工程之间的依赖关系”。子模块通过<parent>指向父 POM,从而继承父 POM 里声明的依赖版本、插件配置、仓库地址等公共信息。它解决的是“重复配置”的问题,让多个子模块不用各自维护一份相同的依赖版本清单。
聚合解决的是“一次构建多个模块”的问题。父 POM 通过<modules>声明自己下面有哪些子模块,这样当你在父工程目录执行 Maven 命令时,Maven 会按顺序把这些子模块全部纳入本次构建,这个机制叫做 reactor(反应堆)。它解决的是“构建顺序和批量构建”的问题。
继承不要求父 POM 和子模块在同一个仓库里,子模块完全可以引用一个外部的父 POM;聚合则要求<modules>里声明的模块目录确实存在于当前工程中。
理解这个区别之后,你就知道为什么“父项目打包”这件事经常出问题:如果父 POM 只配置了<parent>相关的继承结构,但<modules>里没有把所有子模块列进去,那 Maven 执行打包时根本不知道有这些子模块存在,自然不可能去构建它们。
1.2 为什么父 POM 打包不会自动带上子模块
这里的核心问题其实是:你在 IDEA 里点击父项目的package时,Maven 会做什么?
Maven 的 reactor 机制会读取当前 POM 的<modules>,把所有声明的子模块加入构建队列,并按照依赖关系排序后逐个执行对应的 lifecycle。也就是说,如果父 POM 的<modules>配置完整且正确,执行mvn package时 Maven 确实会依次构建所有子模块。这在命令行下表现得非常明显:你会看到 Build Reactor 列表里列出了 parent 和各个子模块。
但为什么大家会觉得很困惑?因为大多数人忽略了packaging这个设置对 Maven 构建行为的影响。
父 POM 的<packaging>有三种常见类型:
| packaging | 作用 | 典型场景 |
|---|---|---|
pom | 只作为一个描述性 POM,本身不产生任何可部署的产物,只用来聚合模块或管理依赖 | 父工程、聚合工程 |
jar | 会被构建成一个可复用的 JAR 包 | 普通 Java 库、Spring Boot 模块 |
war | 会被构建成一个 Web 应用包 | 传统 Web 项目 |
当父项目的<packaging>是pom时,Maven 在父项目上执行package并不会产生一个 jar 包,它只会帮你去触发子模块的构建,同时把父 POM 自身安装到本地仓库或部署到远程仓库。如果你把父项目设置成jar,Maven 就会试图把父 POM 打成一个 jar 包,而这个 jar 包里通常是空的,没有实际代码,没有任何意义。更关键的是,这种错误的 packaging 设置会让 Maven 的 reactor 行为变得奇怪,父项目自身会执行完整的 jar 构建流程,导致整体构建时间变长,也可能掩盖真正的问题。
所以你在 IDEA 里看到“父项目打包不打包子项目”,先不要急着怀疑 IDEA 的 Maven 插件,第一步永远是去查父 POM 的 packaging 和 modules 配置。
1.3 一个最典型的父 POM 结构
我直接给一个典型的聚合工程父 POM 示例,你看完就明白正确的结构长什么样了。
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.example</groupId> <artifactId>demo-parent</artifactId> <version>1.0.0-SNAPSHOT</version> <!-- 关键:父项目 packaging 必须为 pom --> <packaging>pom</packaging> <modules> <module>demo-common</module> <module>demo-service</module> <module>demo-web</module> </modules> <properties> <spring.boot.version>2.7.18</spring.boot.version> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> </properties> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>${spring.boot.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <build> <pluginManagement> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.1</version> <configuration> <source>${maven.compiler.source}</source> <target>${maven.compiler.target}</target> </configuration> </plugin> </plugins> </pluginManagement> </build> </project>注意<modules>里写的是模块的相对路径(相对父 POM 的目录),不是 artifactId。很多人把<module>里的内容写成demo-common,但实际目录名可能叫common-core,这会导致 Maven 找不到模块目录而报错或跳过。
1.4 IDEA 里“父项目”和“子项目”的展示逻辑
IDEA 的 Maven 工具窗口里,每一个 Maven 工程都会被识别为一个根节点,父项目会显示为父节点,子模块会折叠在父节点下面。如果你发现 IDEA 里只显示了一个父项目,没有展开看到子模块,那大概率是你的<modules>配置有问题,或者 IDEA 还没有成功导入子模块。
这时候不要急着去改代码,先执行一次 Maven 的reimport。在 IDEA 右侧 Maven 面板里点击刷新按钮,或者在 pom.xml 上右键选择Maven > Reload Project。重新加载后,父节点下面应该出现所有子模块。
一个小技巧:IDEA 底部有一个 Maven 工具栏,你可以在View > Tool Windows > Maven里打开它。它会把所有模块按照层级展示出来,每层都可以展开看 Lifecycle、Dependencies、Plugins。如果你的子模块没出现在这里,那你打包的时候怎么折腾都不会带上它们。
2. 核心设置:packaging、modules 和父子依赖
2.1 packaging 写成 pom 才是父项目的地基
前面说过,父项目 packaging 必须是pom,这是聚合工程的铁律。很多从单体项目转多模块开发的同学,习惯性地把父项目 packaging 留空。Maven 默认 packaging 是jar,这样父项目就不算一个合格的聚合工程,虽然 Maven 有时候能容错运行,但各种奇怪问题会接踵而来。
如果父 POM 的 packaging 是 jar,执行mvn package时,Maven 会把父项目当作一个普通 Java 模块来构建,它不会去检查<modules>,自然也不会构建子模块。更坑的是,它还会执行编译流程,要求父目录下必须有源码目录和 Java 文件,否则编译报错。
所以你如果遇到“父项目打包时子项目完全不参与”,第一步就是确认<packaging>pom</packaging>有没有写。没写的话,补上。
2.2 modules 里写的是模块路径,不是 artifactId
再看一遍<modules>标签的写法。很多人会在这里犯一个非常隐蔽的错:写对了模块名,但模块实际目录名不匹配。
假设你的子模块 artifactId 叫demo-common,但磁盘上的目录叫common。Maven 对<module>标签的解析规则是:把它当作相对路径,去父 POM 所在目录下找这个路径,找到后读取该目录下的 pom.xml,再通过 pom.xml 里的 artifactId 来确认模块身份。如果你写的是demo-common,目录却叫common,Maven 就会报错找不到模块。
还有一种情况:模块目录里没有 pom.xml。常见的错误是把一个普通目录误加进<modules>,导致 reactor 构建时报错。
所以在配置<modules>时,务必确认每个路径都能找到对应目录,且目录下存在 pom.xml。
2.3 子模块如何正确引用父 POM
子模块的 pom.xml 里需要声明 parent,这样才能继承父 POM 的依赖和插件配置。标准写法如下。
<parent> <groupId>com.example</groupId> <artifactId>demo-parent</artifactId> <version>1.0.0-SNAPSHOT</version> <relativePath>../pom.xml</relativePath> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>demo-common</artifactId>这里有一个<relativePath>标签。它表示父 POM 相对于子模块 POM 的路径。默认情况下,Maven 会先查看../pom.xml,如果找不到再去本地仓库找。建议在子模块中显式写上<relativePath>,一方面加速解析,另一方面避免 Maven 跑到远程仓库找父 POM,导致拿到旧版本。
不过要注意,如果你本地仓库有同 groupId、同 artifactId、同 version 的旧版父 POM,而子模块强制指定了relativePath,那它会优先使用相对路径下的父 POM,不会受影响。
2.4 dependencyManagement 和 parent 的关系
父 POM 里用<dependencyManagement>统一管理依赖版本,这是多模块项目最常用的做法。它不会立即给子模块引入依赖,而是定义了一份“版本字典”,子模块需要哪个依赖就自己声明,但不写版本号。
<dependencyManagement> <dependencies> <dependency> <groupId>com.example</groupId> <artifactId>demo-common</artifactId> <version>${project.version}</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <version>${spring.boot.version}</version> </dependency> </dependencies> </dependencyManagement>子模块里这样就够了:
<dependencies> <dependency> <groupId>com.example</groupId> <artifactId>demo-common</artifactId> </dependency> </dependencies>这样做的好处是:版本号在父 POM 里只出现一次,升级版本时只改父 POM,不用每个子模块都去动。
这里会引出一个模块间依赖的坑:如果demo-service依赖demo-common,而demo-common没有被显式包含在聚合构建里,或者没有被安装到本地仓库,那么单独构建demo-service时可能报错找不到依赖。后面会专门说这个问题。
3. IDEA 中实操:从配置到验证一套完整流程
3.1 准备标准的多模块工程结构
在 IDEA 里手把手搭一个多模块工程,建议按下面的目录结构来。
demo-parent/ ├── pom.xml ├── demo-common/ │ ├── pom.xml │ └── src/main/java/... ├── demo-service/ │ ├── pom.xml │ └── src/main/java/... └── demo-web/ ├── pom.xml └── src/main/java/...在 IDEA 中创建时,“父工程”不要勾选模板,只需在右侧 Maven 坐标里填好 groupId、artifactId、version,然后修改父 POM 的 packaging 为 pom,再手动把<modules>配置写进去。
每个子模块可以直接在父工程目录下右键New > Module,选择 Maven 类型创建。IDEA 会自动补全子模块的<parent>部分。
如果你是从 Git 上拉下来的现成工程,直接以父 POM 作为工程文件打开,IDEA 会自动识别并导入子模块。
3.2 IDEA Maven 面板的正确查看方式
打开 IDEA 右侧 Maven 工具窗口,你会看到类似下面的层级:
demo-parent ├── Lifecycle ├── Dependencies ├── Plugins └── demo-common ├── Lifecycle ├── Dependencies └── Plugins每个子模块下面都有独立的 Lifecycle 列表,里面包含clean、validate、compile、test、package、install、deploy等常用命令。这个列表实际上是 Maven 默认生命周期各个 phase 的映射。
需要留意的一点是:IDEA 上显示的 Lifecycle 列表只是方便你快速执行某个 phase,它并不代表 Maven 内部只有这些命令。你在父项目上点package,Maven 实际执行的是从 lifecycle 第一个 phase 到package的全部阶段,对当前 reactor 内的所有模块都生效。
如果你只想构建某个子模块,可以在 Maven 面板中展开该子模块,右键它的package,这样 Maven 只会构建该模块以及它依赖的其他模块。但这里有个细节:如果该子模块依赖的兄弟模块还没有安装到本地仓库,直接点击它的package也能成功,前提是这个兄弟模块也在这个 reactor 中,且你是用父项目触发的。
3.3 三种打包方式对比:package / install / deploy
IDEA 的 Maven 面板里,package、install、deploy是三个高频按钮,很多人分不清它们的区别,在这个问题上也很关键。
| 命令 | 行为 | 产物去向 | 场景 |
|---|---|---|---|
mvn package | 编译、测试并打包 | 本模块 target 目录 | 只想看看产物,或本地调试验证 |
mvn install | 编译、测试、打包并安装到本地仓库 | 本模块 target + 本地 Maven 仓库 | 需要被其他本地工程依赖 |
mvn deploy | 编译、测试、打包、安装并部署到远程仓库 | 本地仓库 + 私服/中央仓库 | 发布给团队或外部使用 |
在父项目上执行package,子模块的 jar 只会出现在各个子模块自己的 target 目录,不会安装到本地仓库。如果兄弟模块之间互相依赖,而且没有先 install 过,那么单独对某个子模块执行package时,它去找被依赖的兄弟模块,只能去本地仓库找,找不到就会报错。
这时候有两种解法:一是先在父项目上执行install,把所有子模块装进本地仓库,再单独打包;二是用后面要讲的-pl和-am参数,让 Maven 在你指定构建目标模块的同时,自动把依赖到的兄弟模块也加进 reactor。
3.4 只打包某个子模块的正确姿势
很多场景下你并不需要把整个父项目全部打包,只想打包demo-web这一个模块。但直接对demo-web执行mvn package,如果它依赖demo-common,而本地仓库里没有demo-common的对应版本,就会直接失败。
正确做法是在父项目目录下执行带-pl和-am参数的 Maven 命令:
mvn package -pl demo-web -am参数说明:
-pl后面跟的是要构建的模块列表,可以写多个,用逗号分隔,例如-pl demo-web,demo-service。-am是--also-make的缩写,意思是构建指定模块的同时,把模块依赖到的其他模块也加入 reactor 一起构建。- 如果不加
-am,Maven 只会构建指定模块,不会去构建它的兄弟依赖模块。
在 IDEA 里操作的话,可以在 Maven 面板右上角的执行配置里填入这些参数。点开面板上的Maven Executor设置,或者在 Runner 的 VM Options 旁边的 Command line 里手动输入。
这个组合参数在 CI/CD 流水线上也很有用。比如 Jenkins 里面配置打包任务时,只需要构建某个改动的服务,直接在构建命令里加上-pl和-am,能省下大量全量构建的时间。
3.5 全量打包:父项目 install 的真实行为
当你在 IDEA 里选中父项目,执行install,Maven 会启动 reactor,把父 POM 以及<modules>里声明的所有子模块按依赖关系排序后逐一构建。执行过程中,每个模块都会经历完整的 lifecycle:compile、test、package、install。
这个完整过程跑下来,最终所有子模块的 jar 都会安装到本地 Maven 仓库。之后再对单个子模块单独执行package,就能在本地仓库找到对应的兄弟依赖,不会报错。
所以,遇到“父项目打包不带子项目”的另一个常见原因,是你执行的是package而不是install,并且子模块之间存在依赖关系。但注意,这并不能解释“子模块根本没有构建”的情况。真正“子模块完全不参与构建”的原因,还是<modules>配置或 packaging 配置有问题。
4. 常见问题排查与技巧实录
4.1 父项目 packaging 没设 pom,直接报错或行为异常
我在排查这类问题时,见过最多的情况就是父 POM 的 packaging 没有写。Maven 默认把它当 jar 处理,执行mvn package时,会尝试编译父项目,如果父项目目录下只有 pom.xml 没有 src,那就会直接编译失败。
这种问题通常表现为:在 IDEA 里右键父项目,点击package,然后控制台报错找不到源码目录,或者干脆 BUILD FAILURE。解决方式很简单,父 POM 加上<packaging>pom</packaging>,重新 reimport 即可。
怎么验证 packaging 生效?执行mvn help:effective-pom,能看到当前 POM 生效后的最终状态,里面会显示 packaging 为 pom。
4.2 modules 标签没有把所有子模块列出来
这是一种非常隐蔽的情况。项目明明有 5 个子模块,但父 POM 的<modules>里只写了 3 个。IDEA 里可能会显示全部 5 个模块,因为 IDEA 可能通过子模块自身的<parent>识别到了它们。但 Maven 的 reactor 只认<modules>里的内容,所以执行父项目打包时,没有被列入的 2 个子模块完全不参与构建。
这种问题的特征是:你看到 IDEA 里项目结构很完整,但构建结果里始终没有那 2 个模块的产物。排查思路是直接打开父 POM,检查<modules>列表,跟实际子模块目录一一比对。
4.3 IDEA 里 Maven 视图没自动刷新,界面和实际工程对不上
IDEA 的 Maven 视图偶尔会“失真”。比如你从 Git 拉取代码后,其他人改了 pom.xml,IDEA 不会每次自动刷新。这时候你看到的结构可能是旧的,某个新增的子模块没有显示,或者某个移除的模块还在列表里。
遇到这种问题,执行一次Reload All Maven Projects。IDEA 会重新解析每个模块的 pom.xml,刷新整个 Maven 视图。在 Maven 面板左上角有一个刷新图标,点击它,或者右键父 POM 选择Maven > Reload Project。
这里有个更隐蔽的情况:IDEA 缓存了错误的模块状态,即使 reload 之后模块仍然不出现。此时可以执行File > Invalidate Caches / Restart,清缓存重启 IDE,再重新导入。
4.4 子模块之间互相依赖,单独 package 子模块失败
这个问题在拆分微服务时特别常见。demo-web依赖demo-service,demo-service依赖demo-common。如果你在 IDEA 里单独对demo-web执行package,而demo-common和demo-service都没有安装到本地仓库,Maven 会报错:
Could not resolve dependencies for project com.example:demo-web:1.0.0-SNAPSHOT Failure to find com.example:demo-common:1.0.0-SNAPSHOT原因是 Maven 对单个模块执行构建时,不会自动去寻找它的兄弟模块,只会去本地仓库找依赖。解决办法有两条:
- 在父项目上执行
mvn install -pl demo-common,demo-service -am,先把需要的兄弟模块安装到本地仓库。 - 以后都从父项目上执行
mvn package -pl demo-web或mvn install -pl demo-web -am,让 Maven 在 reactor 中处理依赖。
建议直接用方案二,一次构建全部搞定。
4.5 另一个经典坑:install 到本地仓库后再打包
有人习惯先在父项目上执行install,把所有模块装进本地仓库,然后再修改某个子模块的代码,再单独对那个子模块执行package。这时候打包用的兄弟依赖,其实是从本地仓库拿的旧版本 jar,不是当前工作区的最新代码。
这就是所谓的“本地仓库污染”。很多诡异的问题由此产生:代码看起来改对了,但运行时的表现还是老样子。
解决办法:在打包前先对依赖的子模块执行一次install,再打包目标模块。或者干脆每次从父项目上用-pl和-am组合,让所有相关模块在本次 reactor 内一并构建,避免使用过期的本地仓库产物。
4.6 常见问题速查表
| 症状 | 根因 | 解决方式 |
|---|---|---|
| 父项目执行 package,子模块完全不构建 | 父 POM 的 packaging 不是 pom,或 modules 没写全 | 检查 packaging 和 modules 配置 |
| 只打包子模块,提示找不到兄弟依赖 | 兄弟依赖未安装到本地仓库 | 用-pl xxx -am,或在父项目先 install |
| IDEA 里看不到新增子模块 | Maven 视图未刷新,或模块未加入 modules | Reload All Maven Projects,改正 modules |
| 构建报错找不到某个模块目录 | modules 里的路径和实际目录名不一致 | 逐一比对 modules 路径 |
| 改代码后打包,运行还是旧逻辑 | 本地仓库拿到旧的兄弟依赖 jar | 全量 install 或用 -am 构建 |
4.7 关于 Jenkins 和发布场景的补充
如果你的项目最终通过 Jenkins 这类 CI 工具打包发布,同样会遇到这个问题。建议在流水线里使用统一的构建命令,例如:
mvn clean install -DskipTests -pl demo-web -am这样做有两个好处:第一,-pl明确指定要发布的目标模块,-am自动把依赖模块带进 reactor,不需要提前手动 install;第二,-DskipTests跳过测试,避免测试环境不稳定导致构建中断。注意不是-Dmaven.test.skip=true,后者连测试代码都不会编译,区别在特定场景下会影响构建结果。
另外,发布到 Docker 或服务器时,除了打包 jar,还要把子模块依赖的配置一并考虑进去。多模块工程中,经常有某个子模块只有配置没有代码,这时候一定要保证它被<modules>包含,否则打包出的服务缺配置文件,部署上去就是各种启动报错。
5. 一个标准的多模块打包示例
这里给一个更完整的 Spring Boot 多模块示例,帮助你落地验证。假设模块结构如下:
demo-parent/ ├── pom.xml ├── demo-common/ │ └── pom.xml ├── demo-service/ │ └── pom.xml └── demo-web/ └── pom.xml父 POM:
<project xmlns="http://maven.apache.org/POM/4.0.0"> <modelVersion>4.0.0</modelVersion> <groupId>com.example</groupId> <artifactId>demo-parent</artifactId> <version>1.0.0-SNAPSHOT</version> <packaging>pom</packaging> <modules> <module>demo-common</module> <module>demo-service</module> <module>demo-web</module> </modules> <properties> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>2.7.18</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> </project>子模块 demo-common,它是被其他模块依赖的基础库,不包含 Spring Boot 启动类:
<project xmlns="http://maven.apache.org/POM/4.0.0"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>com.example</groupId> <artifactId>demo-parent</artifactId> <version>1.0.0-SNAPSHOT</version> <relativePath>../pom.xml</relativePath> </parent> <artifactId>demo-common</artifactId> </project>子模块 demo-service,依赖 demo-common:
<project xmlns="http://maven.apache.org/POM/4.0.0"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>com.example</groupId> <artifactId>demo-parent</artifactId> <version>1.0.0-SNAPSHOT</version> <relativePath>../pom.xml</relativePath> </parent> <artifactId>demo-service</artifactId> <dependencies> <dependency> <groupId>com.example</groupId> <artifactId>demo-common</artifactId> </dependency> </dependencies> </project>子模块 demo-web,它是最终的 Web 启动模块,包含@SpringBootApplication启动类:
<project xmlns="http://maven.apache.org/POM/4.0.0"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>com.example</groupId> <artifactId>demo-parent</artifactId> <version>1.0.0-SNAPSHOT</version> <relativePath>../pom.xml</relativePath> </parent> <artifactId>demo-web</artifactId> <dependencies> <dependency> <groupId>com.example</groupId> <artifactId>demo-service</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>在 IDEA 中,选中父项目 demo-parent,执行:
mvn clean install -DskipTests你会看到控制台输出依次构建 demo-common、demo-service、demo-web。如果只想要 web 这个可执行模块的产物,可以执行:
mvn clean package -DskipTests -pl demo-web -am构建完成后,demo-web/target目录会生成可直接运行的 Spring Boot jar。
我个人的建议是:多模块项目本地开发时,多用install而非package,并且尽量在父项目层发起构建,少对单个子模块直接点按钮。这样能避免兄弟模块依赖版本不同步产生的诡异问题。另外,所有模块统一从父 POM 继承版本,不要在子模块里硬写版本号,否则升级依赖时会非常痛苦。
如果按照上面的步骤配置后还是出现“父项目打包不打包子项目”,那就去检查一下 Maven 的 settings.xml 里有没有配置特殊的 mirror 仓库导致父 POM 解析失败,还有子模块的 pom.xml 是否被 IDEA 标记为“忽略”状态。在 IDEA 的 Maven 设置里有个 Ignored Files 列表,如果某个 pom 被勾选忽略,它就不会出现在 Maven 视图中,构建时自然也不会参与。