Maven pom.xml 配置文件
一、父子POM结构
1.简介
在 Maven 中,pom.xml 是项目的核心构建文件。通过将多个模块的配置抽象到一个父 POM中,子模块可以继承这些通用配置,只关注自己的差异部分,从而达到统一、解耦、协同构建的目的。
父 POM(Parent POM)
父模块的作用类似于“配置模板”,它:
- 管理通用依赖和插件版本
- 配置构建行为、仓库信息
- 聚合多个子模块
子 POM(Module POM)
子模块继承父 POM,仅声明自身特有内容:
- 模块特有的依赖
- 模块特有的构建配置
子 POM 并不是“从属”关系,而是“继承 + 聚合”的组合。
2.结构
multi-module-demo/
├── module-user/
│ └── pom.xml # 子模块 A
├── module-order/
│ └── pom.xml # 子模块 B
├── pom.xml # 父模块(Parent)
3.解析
Maven 在构建过程中,会自底向上解析每个 POM 的继承链,最终形成一个完整的 Effective POM(有效配置):
子模块 POM
↑
父模块 POM
↑
官方 BOM(如 spring-boot-dependencies)
↑
Maven Super POM(默认 POM)
- 子模块不需要重复定义依赖版本、插件等;
- 若子模块中定义了与父模块相同的依赖或插件,将覆盖父模块定义。
4.语法
父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
https://maven.apache.org/xsd/maven-4.0.0.xsd">
<!-- 基础信息 -->
<modelVersion>4.0.0</modelVersion>
<groupId>com.tinci.boot</groupId> <!-- 所有子模块共用 -->
<artifactId>springboot-labs</artifactId> <!-- 父模块名称 -->
<version>1.0.0</version>
<packaging>pom</packaging>
<!-- 模块管理 -->
<modules>
<module>module-user</module>
</modules>
</project>
实际上
springboot-labs
虽然通过<modules>
声明了module-user
是它的一个模块,但这只是为了构建时统一执行,而不是为了继承配置。Maven 不会自动认为springboot-labs
是module-user
的父项目,除非module-user
中使用了<parent>
元素声明父pomspringboot-labs
子pom中继承父pom:不需要声明 < groupId >、< version >、< packaging > 等信息,因为这些都可以从 父 POM 中继承
<project>
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.tinci.boot</groupId>
<artifactId>springboot-labs</artifactId>
<version>1.0.0</version>
</parent>
<artifactId>module-user</artifactId>
</project>
二、依赖引入方式
1. 直接引入依赖(最常见)
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>6.1.1</version>
</dependency>
</dependencies>
- 明确指定依赖坐标
- 会被打包到最终项目中(除非 scope 特殊)
作用域 生命周期影响 打包包含 典型使用场景 compile 编译、测试、运行、打包 ✅ 是 项目核心依赖(如 Spring Core) provided 编译、测试 ❌ 否 容器提供依赖(如 Servlet API) runtime 测试、运行 ✅ 是 运行时实现(如 JDBC 驱动) test 仅测试阶段 ❌ 否 测试框架(如 JUnit) system 显式本地路径依赖 ⚠️ 有条件 特殊本地 JAR(不推荐生产使用) scope(依赖作用域)
2.通过 < dependencyManagement > 引入(只声明版本,不引入依赖)
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.83</version>
</dependency>
</dependencies>
</dependencyManagement>
子模块可以这样用,而不用写版本:
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
</dependency>
适用场景:
- 父子模块版本统一管理
- 避免多模块中写多个版本号
3. 使用 BOM(导入依赖版本清单)
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.kaishu</groupId>
<artifactId>kaishu-dependencies</artifactId>
<version>${revision}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
导入之后,子模块可以直接使用 Spring Boot 相关依赖而不用写版本号。
这里的pom文件spring-boot-dependencies其实就是一个BOM(专门用于集中管理和统一版本控制)
4.传递依赖(Transitive Dependency)
A 依赖 B,B 依赖 C,=> A 自动依赖了 C
你没写它,但它通过你依赖的库自动引入了
5.使用 排除依赖
用于清理多余的传递依赖:
<dependency>
<groupId>com.xxxx</groupId>
<artifactId>xx-lib</artifactId>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
6.父 POM 引入依赖
在公司项目中很常见,将通用依赖放进父模块,让所有子项目都继承:
<parent>
<groupId>com.mycompany</groupId>
<artifactId>project-parent</artifactId>
<version>1.0.0</version>
</parent>
然后在父 POM 的 < dependencyManagement > 或 < dependencies > 中集中定义版本。
7.本地仓库 / 私服引入(Nexus、Artifactory)
用于引入私有 jar:
<repositories>
<repository>
<id>my-nexus</id>
<url>https://nexus.mycorp.com/repository/maven-public/</url>
</repository>
</repositories>
小结
引入方式 | 是否写版本 | 是否实际引入 | 场景说明 |
---|---|---|---|
<dependencies> | ✅ | ✅ | 项目直接使用 |
<dependencyManagement> | ✅ | ❌ | 统一版本管理 |
BOM + import | ✅ | ❌ | 集中式依赖版本 |
传递依赖 | ❌ | ✅(隐式) | 自动引入 |
排除依赖 | ❌ | ❌ | 精简依赖树 |