/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */
#content_views .toc,
/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */
#content_views.markdown_views > p:empty:has(+ .toc),
#content_views.markdown_views > .toc + p:empty,
/* 富文本旧版目录标记 */
#content_views.htmledit_views #main-toc,
#content_views.htmledit_views #hr-toc,
#content_views.htmledit_views p[id*=\”-toc\”] {
display: none !important;
}
/* 目录去掉后,紧跟的首个标题不再多出一块上边距 */
#content_views.markdown_views > .toc + h1,
#content_views.markdown_views > .toc + h2,
#content_views.markdown_views > .toc + h3,
#content_views.markdown_views > .toc + h4,
#content_views.markdown_views > .toc + p:empty + h1,
#content_views.markdown_views > .toc + p:empty + h2,
#content_views.markdown_views > .toc + p:empty + h3,
#content_views.markdown_views > .toc + p:empty + h4 {
margin-top: 0 !important;
}
<packaging>pom</packaging>:集团总部不生产产品,只发号施令
一句话记忆:jar 是成品,war 是外卖盒,pom 是文件夹——它自己不是产品,但能组织一堆产品。
一、先看比喻:总部 vs 工厂
想象一个集团公司:
- 集团总部:不生产具体产品,只负责定制度、管预算、协调各个子公司。总部本身不是一个“可售卖的商品”。
- 子公司 A:生产饼干,产出的是一盒盒饼干(jar)。
- 子公司 B:做外卖套餐,产出的是打包好的餐盒(war)。
Maven 里的 <packaging>pom</packaging>,就是那个集团总部。
它自己不产出 jar,也不产出 war。它的价值在于:
而默认的 <packaging>jar</packaging> 是“工厂”,产出一个能放进 classpath 的 jar 包;<packaging>war</packaging> 是“外卖打包站”,产出一个能丢进 Tomcat 的 war 包。
记忆钩子:pom 是文件夹,jar 是文件,war 是外卖盒。
二、Maven 的 packaging 有哪几种?
| jar(默认) | .jar | 普通 Java 库、Spring Boot 可执行 jar | 一盒成品饼干 |
| war | .war | 传统 Web 应用,部署到 Tomcat | 一份打包外卖 |
| pom | 不产生构件,只安装 pom 文件 | 父工程、聚合工程 | 集团总部 / 文件夹 |
| maven-plugin | 插件 jar | 自定义 Maven 插件 | 工具箱 |
| ear / rar | 企业包 / 资源包 | 较少用 | 大礼包 |
重点记住:pom 打包的模块,mvn package 不会生成 jar 或 war。 它只会在 install 时把 pom.xml 本身安装到本地仓库,供子模块继承或引用。
三、它到底有什么意义?两大用途
用途 1:父工程——统一“家规”
子模块通过 <parent> 继承父工程,父工程用 packaging=pom 统一管理:
<!– 父工程 pom.xml –>
<groupId>com.example</groupId>
<artifactId>my-project-parent</artifactId>
<version>1.0.0</version>
<packaging>pom</packaging>
<properties>
<java.version>17</java.version>
<spring.version>6.1.0</spring.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
子模块:
<parent>
<groupId>com.example</groupId>
<artifactId>my-project-parent</artifactId>
<version>1.0.0</version>
</parent>
好处:版本只写一次,子模块不用重复写 <version>,升级时改父工程一处即可。
你熟悉的 spring-boot-starter-parent 就是 packaging=pom 的典型——它自己不产出任何 jar,只负责给所有 Spring Boot 子模块定规矩。
用途 2:聚合工程——统一“调度”
父工程用 <modules> 把子模块聚在一起:
<packaging>pom</packaging>
<modules>
<module>user-service</module>
<module>order-service</module>
<module>common-utils</module>
</modules>
在父工程目录执行一次 mvn clean install,Maven 会按依赖关系自动构建所有子模块,这叫 reactor 构建。
记忆钩子:父工程管“怎么建”,聚合工程管“建哪些”。两者常写在同一个 pom 里。
四、和 SpringMVC / Spring Boot 项目的关系
典型的多模块 Spring 项目结构:
my-shop/
├── pom.xml ← packaging=pom,父工程 + 聚合
├── common/
│ └── pom.xml ← packaging=jar,公共工具库
├── user-service/
│ └── pom.xml ← packaging=jar,业务模块
└── web-app/
└── pom.xml ← packaging=war 或 jar,Web 入口
- 根 pom.xml 用 pom 打包:不产出构件,只做继承和聚合。
- common 用 jar:产出公共 jar,被其他模块依赖。
- web-app 用 war 或 Spring Boot 可执行 jar:最终部署单元。
一句话:pom 打包的模块是“组织者”,不是“产品”。
五、怎么记?三个钩子
钩子 1:口诀
pom 是总部,只发号令不出货;
jar 是饼干,war 是外卖盒;
父工程定规矩,聚合工程管调度。
钩子 2:三问法
看到 packaging=pom,问三句:
钩子 3:文件夹类比
packaging=pom 的模块就像一个文件夹:文件夹本身不是文件内容,但它里面可以装很多文件,还能规定这些文件怎么命名、怎么组织。
六、面试 30 秒版
packaging=pom 表示该 Maven 模块不产生可部署构件,通常用于父工程或聚合工程。父工程通过 <parent> 被子模块继承,在 dependencyManagement、properties、build 中统一管理依赖版本和插件配置;聚合工程通过 <modules> 组织多模块,实现一次构建。它本身不能直接运行,install 时只把 pom 文件安装到本地仓库。Spring Boot 的 spring-boot-starter-parent 就是典型例子。
七、常见坑
父工程 packaging 写成 jar
会生成一个几乎空的 jar,而且继承/聚合语义不规范。父工程就该用 pom。
以为 packaging=pom 的模块能 java -jar
不能。它没有可执行入口,也不是部署单元。
在 packaging=pom 的模块里配 spring-boot-maven-plugin 的 repackage
没有主类、没有可执行 jar,repackage 会报错。该插件应放在可执行子模块里。
子模块忘了写 <parent> 却怪版本管理不生效
dependencyManagement 的继承依赖 <parent> 关系,不是靠目录位置自动生效。
聚合工程和父工程混为一谈
聚合靠 <modules>(管构建范围),继承靠 <parent>(管配置复用)。两者可以合一,但概念不同。
八、记忆卡片
pom 是总部:不产 jar 不产 war,只定规矩管调度。
父工程靠 <parent> 继承,聚合工程靠 <modules> 组织。
jar 是饼干,war 是外卖盒,pom 是文件夹。
能运行的是子模块,发号施令的是 pom。
网硕互联帮助中心





评论前必须登录!
注册