Maven使用之POM文件
- pom.xml文件在项目目录中所处的位置?
- pom.xml文件在Maven项目中所处的地位?
-
- 一、从结构上看:它是项目的根配置
- [二、从执行流程看:它是 Maven 的输入](#二、从执行流程看:它是 Maven 的输入)
- 三、它主要定义哪些内容
-
- [1 项目身份](#1 项目身份)
- [2 项目依赖](#2 项目依赖)
- [3 构建规则](#3 构建规则)
- [4 生命周期行为](#4 生命周期行为)
- [5 多模块关系](#5 多模块关系)
- 四、从重要性看:它比代码更像项目的大脑
- pom.xml文件包含的内容
- Maven拉依赖,是拉什么,是从哪儿拉到哪儿?
-
- [1. Maven 拉的是什么?](#1. Maven 拉的是什么?)
-
- [(1)jar 包(最常见)](#(1)jar 包(最常见))
- [(2)POM 文件](#(2)POM 文件)
- (3)校验文件(可选)
- [2. GAV 坐标是什么?](#2. GAV 坐标是什么?)
- [3. 从哪儿拉?](#3. 从哪儿拉?)
- [4. 拉到哪儿?](#4. 拉到哪儿?)
- [5. 拉完之后怎么用?](#5. 拉完之后怎么用?)
- [6. 实际执行过程(以 mvn compile 为例)](#6. 实际执行过程(以 mvn compile 为例))
- pom.xml文件的作用?从实际用到的地方入手。
-
- 什么时候会读取pom.xml文件?
- [1. 执行 Maven 命令时(最常见)](#1. 执行 Maven 命令时(最常见))
- [2. IDEA 导入 / 打开 Maven 项目时](#2. IDEA 导入 / 打开 Maven 项目时)
- [3. 修改 pom.xml 时](#3. 修改 pom.xml 时)
- [4. 下载依赖时](#4. 下载依赖时)
- [5. 多模块项目构建时](#5. 多模块项目构建时)
- 一个容易误解的点
pom.xml文件在项目目录中所处的位置?
它在项目根目录下,与src文件夹同级。

pom.xml文件在Maven项目中所处的地位?
pom.xml 在 Maven 项目里的地位,可以理解成:
它是 Maven 项目的"总说明书 + 构建配置中心 + 项目模型定义"。
Maven 几乎所有动作,都是先读 pom.xml 再决定怎么干。
如果没有 pom.xml:
bash
mvn compile
mvn package
mvn install
通常直接失败:
text
The goal you specified requires a project to execute
but there is no POM in this directory
说明 Maven 不知道:
- 你是谁(项目信息)
- 代码在哪
- 依赖有哪些
- 怎么编译
- 怎么打包
可以把 Maven 项目想象成一个工厂:
text
源码 → 原材料
依赖 → 外购零件
插件 → 机器设备
Maven → 工厂调度系统
pom.xml → 工厂总设计图
没有设计图,工厂不知道生产什么。
一、从结构上看:它是项目的根配置
典型目录:
text
hello-world
├── pom.xml
├── src
│ ├── main
│ │ └── java
│ └── test
└── target
其中:
text
pom.xml
↑
整个项目的中心
二、从执行流程看:它是 Maven 的输入
执行:
bash
mvn package
内部大概:
text
读取 pom.xml
↓
生成项目模型(Project)
↓
解析继承
↓
解析依赖
↓
确定生命周期
↓
绑定插件
↓
执行目标
↓
输出结果
所以:
text
pom.xml
↓
Project Object Model
↓
Maven运行依据
这里 POM 的全称就是:
Project Object Model(项目对象模型)
意思不是"配置文件"。
而是:
Maven把项目抽象成一个对象模型。
三、它主要定义哪些内容
1 项目身份
决定项目是谁。
xml
<groupId>com.demo</groupId>
<artifactId>hello</artifactId>
<version>1.0</version>
组成:
text
GAV
groupId
artifactId
version
唯一标识一个构件。
例如:
text
com.demo:hello:1.0
2 项目依赖
定义需要哪些 jar。
xml
<dependencies>
<dependency>
...
</dependency>
</dependencies>
作用:
text
告诉Maven:
编译时请把这些库准备好
3 构建规则
定义怎么编译。
xml
<build>
例如:
- 用哪个编译插件
- Java版本
- 打包方式
4 生命周期行为
例如:
bash
mvn compile
mvn test
mvn package
mvn install
每一步执行什么插件。
5 多模块关系
父项目:
xml
<modules>
子项目:
xml
<parent>
决定整个工程结构。
四、从重要性看:它比代码更像项目的大脑
有时候:
text
代码没变
pom改了
整个项目行为变了
例如:
改:
xml
<packaging>jar</packaging>
变:
xml
<packaging>war</packaging>
项目瞬间从:
text
普通Java应用
↓
Web应用
再比如:
改依赖:
xml
spring 5
↓
spring 6
整个运行结果都可能变化。
一句话记忆:
text
源码决定"程序做什么"
pom.xml决定"项目怎么被构建出来"
再往深一层,可以继续问:
为什么 Maven 不直接读取目录,而非要先把 pom.xml 转成 Project Object Model 对象?
那个问题会进入 Maven 的核心架构(Model → Lifecycle → Plugin → Artifact)。
pom.xml文件包含的内容
最精简的pom文件:
java
<?xml version="1.0" encoding="UTF-8"?>
<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>hello-world-maven-ide</artifactId>
<version>1.0-SNAPSHOT</version>
</project>
pom文件解析
这是一个最精简的 Maven 项目 pom.xml,我逐行给你拆解含义:
xml
<?xml version="1.0" encoding="UTF-8"?>
- XML 文件声明,版本 1.0,编码 UTF-8。
xml
<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">
- 根标签
<project> xmlns声明 Maven POM 命名空间xsi:schemaLocation指定 XML 约束文件,用于 IDE 校验语法
xml
<modelVersion>4.0.0</modelVersion>
- POM 模型版本
- 目前 Maven 统一使用
4.0.0,几乎不会改。
xml
<groupId>com.example</groupId>
- 组织/公司域名(倒序)
- 类似 Java 包名前缀,这里是示例域名
com.example
xml
<artifactId>hello-world-maven-ide</artifactId>
- 项目/模块名称
- 这个项目的名字:
hello-world-maven-ide
xml
<version>1.0-SNAPSHOT</version>
- 版本号
1.0:主版本SNAPSHOT:表示开发中、快照版本,还未正式发布
xml
</project>
- 根标签结束。
整体总结
这是一个空的、无任何依赖、无插件的最小 Maven 项目配置:
- 坐标:
com.example:hello-world-maven-ide:1.0-SNAPSHOT - 作用:仅用来标识项目,不能运行任何代码,也没有引入 Spring、Servlet 等任何依赖。
如果你需要,我可以帮你:
- 加上 JUnit 测试依赖
- 加上 Maven 编译插件
- 改成可运行的 Java 项目
丰富pom文件内容
我给你直接改成可编译、可运行、带测试的完整 pom.xml,你直接覆盖原文件即可:
xml
<?xml version="1.0" encoding="UTF-8"?>
<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>hello-world-maven-ide</artifactId>
<version>1.0-SNAPSHOT</version>
<!-- 指定JDK版本,解决编码和编译问题 -->
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<!-- 单元测试依赖 -->
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
</dependencies>
<!-- 构建插件:打包、编译 -->
<build>
<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>
<encoding>${project.build.sourceEncoding}</encoding>
</configuration>
</plugin>
</plugins>
</build>
</project>
加了哪些东西:
-
<properties>- 统一指定 JDK 版本(这里用 11,你也可以改成 8 / 17)
- 设置编码为 UTF-8,避免中文乱码
-
<dependencies>- 加入了 JUnit 4 测试依赖,可以写单元测试
-
<build>插件maven-compiler-plugin:确保 Maven 用指定 JDK 编译
配套使用建议:
-
目录结构:
src ├── main │ └── java │ └── com │ └── example │ └── App.java └── test └── java └── com └── example └── AppTest.java -
执行命令:
mvn compile编译mvn test运行测试mvn package打成 jar 包
Maven拉依赖,是拉什么,是从哪儿拉到哪儿?
Maven拉依赖,是读取pom.xml文件中的<dependencies>标签下的<dependency>内容,获取依赖的GAV坐标。
Maven 拉依赖,本质上是:
根据
pom.xml中声明的依赖坐标(GAV),从远程仓库下载对应的构件(artifact),保存到本地仓库,再加入项目构建路径(classpath)。
例如:
xml
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
</dependencies>
1. Maven 拉的是什么?
不是拉源码,而是拉:
(1)jar 包(最常见)
真正运行代码:
text
junit-4.13.2.jar
里面是:
text
.class
META-INF
资源文件
(2)POM 文件
描述这个依赖自身还依赖谁。
例如:
text
junit-4.13.2.pom
内容类似:
xml
<dependencies>
<dependency>
...
</dependency>
</dependencies>
Maven 会继续解析。
这叫:
传递依赖(Transitive Dependency)
(3)校验文件(可选)
例如:
text
.sha1
.md5
用于验证下载完整性。
2. GAV 坐标是什么?
Maven 用 GAV 唯一定位依赖。
text
G = groupId
A = artifactId
V = version
例如:
xml
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
对应:
text
junit:junit:4.13.2
像身份证:
text
组织:项目:版本
3. 从哪儿拉?
优先级一般:
text
① 本地仓库
↓
② 私服(如果配置)
↓
③ 中央仓库
本地仓库
默认:
Mac/Linux:
text
~/.m2/repository
例如:
text
~/.m2/repository/junit/junit/4.13.2/
里面:
text
junit-4.13.2.jar
junit-4.13.2.pom
私服(企业常用)
例如:
text
Nexus
Artifactory
公司统一缓存依赖。
中央仓库
默认:
text
https://repo.maven.apache.org/maven2
4. 拉到哪儿?
最终放到:
text
本地仓库 ~/.m2/repository
目录结构由 GAV 自动生成:
依赖:
text
junit:junit:4.13.2
映射:
text
~/.m2/repository
└── junit
└── junit
└── 4.13.2
├── junit-4.13.2.jar
└── junit-4.13.2.pom
5. 拉完之后怎么用?
下载结束后。
Maven:
text
jar
↓
加入 classpath
↓
javac 编译
↓
java 运行
于是代码能:
java
import org.junit.Test;
否则:
text
package org.junit does not exist
6. 实际执行过程(以 mvn compile 为例)
text
读取 pom.xml
↓
解析 dependencies
↓
得到 GAV
↓
查 ~/.m2
↓
没有
↓
请求远程仓库
↓
下载 jar + pom
↓
存入 ~/.m2
↓
递归下载传递依赖
↓
加入 classpath
↓
开始编译
所以一句话总结:
Maven 拉依赖,不是"把代码拷到项目里",而是根据 pom 中的 GAV,把构件(jar、pom 等)从远程仓库下载到本地仓库,再挂到当前项目的 classpath 上供编译和运行使用。
pom.xml文件的作用?从实际用到的地方入手。
什么时候会读取pom.xml文件?
这个问题问到 Maven 的执行时机了。
先给结论:
几乎所有 Maven 命令开始执行时,第一步都是读取
pom.xml。
因为 Maven 要先知道:
text
这是哪个项目?
依赖是什么?
执行哪个生命周期?
插件怎么配置?
不知道这些,就没法继续。
1. 执行 Maven 命令时(最常见)
例如:
bash
mvn compile
内部大概:
text
启动 Maven
↓
找当前目录 pom.xml
↓
读取并解析
↓
生成 Project Model
↓
解析依赖
↓
执行 compile
再比如:
bash
mvn package
mvn install
mvn test
mvn clean
都会先读 pom.xml。
所以:
bash
mvn compile
不是:
text
直接编译
而是:
text
先读pom
再编译
2. IDEA 导入 / 打开 Maven 项目时
例如:
text
File
↓
Open
↓
选择项目目录
如果发现:
text
pom.xml
IDEA 会:
text
读取pom
↓
解析依赖
↓
生成模块
↓
建立索引
↓
下载依赖
所以第一次打开项目常看到:
text
Import Maven Project
其实就是:
text
导入 pom.xml
3. 修改 pom.xml 时
例如你改:
xml
<dependency>
保存。
IDEA 通常会:
text
检测pom变化
↓
重新导入
↓
重新解析依赖
你会看到:
text
Reload Maven Project
4. 下载依赖时
例如:
bash
mvn dependency:tree
过程:
text
读pom
↓
拿dependencies
↓
解析依赖树
5. 多模块项目构建时
假设:
text
project
├── pom.xml
├── order
│ └── pom.xml
└── user
└── pom.xml
执行:
bash
mvn package
会:
text
读父pom
↓
读子pom
↓
组装项目模型
↓
开始构建
一个容易误解的点
读取 pom.xml ≠ 每次都重新下载依赖。
例如:
第一次:
text
读pom
↓
发现缺依赖
↓
下载
第二次:
text
读pom
↓
发现本地已有
↓
直接使用
所以:
text
读pom:几乎每次执行
下载依赖:按需执行
最后给一句记忆:
text
Maven 的运行入口通常不是源码,而是 pom.xml。
源码是材料,pom 是施工图。
你前面已经串起来了:
mvn compile → 读取 pom → 解析依赖 → 调插件 → javac → class
再往下一层,就是:
Maven 是怎么找到当前目录对应的 pom.xml 的(工作目录、-f 参数、父子 POM 查找)。