如果你刚开始接触 Java 后端开发,经常会看到:
bash
mvn clean
mvn install
mvn package
mvn test
项目里还经常有一个:
pom.xml
很多初学者的第一反应是:
Maven 不就是一个 Java 的包管理工具吗?
其实不完全是。
Maven 更准确地说,是一个 Java 项目的构建与项目管理工具。
它主要帮助我们解决:
- 项目怎么编译
- 测试怎么运行
- 依赖怎么管理
- 项目怎么打包
- 多模块项目怎么组织
- 构建过程怎么标准化
Apache Maven 官方也将它定位为用于 Java 项目构建和管理的工具,并通过 POM 和插件定义项目的构建过程。(Apache Maven)
一、没有 Maven 的时候,我们需要做什么?
假设我们有一个 Java 项目:
css
src/
└── Main.java
我们想运行它,大概需要经历:
arduino
Java 源代码
↓
javac 编译
↓
.class 文件
↓
运行
但真实项目很快就复杂起来了。
比如我们的项目需要:
erlang
Spring
MySQL Driver
MyBatis
Jackson
Lombok
JUnit
...
那么问题来了:
这些 Jar 包从哪里下载?
Jar 包之间还有依赖关系怎么办?
项目怎么编译?
测试怎么执行?
最后怎么打包成 Jar?
如果全部手工处理,会非常麻烦。
Maven 就是用来解决这一系列问题的。
二、Maven 最核心的三个东西
入门 Maven,可以先记住三个概念:
POM、Repository、Lifecycle。
可以简单理解成:
POM
↓
告诉 Maven:项目是什么、依赖什么
Repository
↓
告诉 Maven:依赖从哪里获取
Lifecycle
↓
告诉 Maven:项目怎么构建
这三个概念基本贯穿 Maven 的整个使用过程。
三、POM 是什么?
POM 全称:
css
Project Object Model
也就是:
项目对象模型。
它通常就是项目根目录下的:
pom.xml
例如:
xml
<project>
<groupId>com.example</groupId>
<artifactId>demo</artifactId>
<version>1.0.0</version>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>3.5.0</version>
</dependency>
</dependencies>
</project>
你可以把 pom.xml 理解成:
这个 Java 项目的身份证 + 配置文件。
它里面可以描述:
项目叫什么
项目版本是多少
使用什么 Java 版本
依赖哪些第三方库
使用哪些插件
怎么打包
父项目是谁
有哪些子模块
所以看到一个 Maven 项目,第一件事通常就是:
打开 pom.xml
四、dependency 是 Maven 最常见的配置
例如:
xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>3.5.0</version>
</dependency>
它表示:
我的项目需要
spring-boot-starter-web这个依赖。
这里有三个特别重要的字段。
groupId
表示组织或者项目所属的组织:
xml
<groupId>org.springframework.boot</groupId>
可以理解成:
哪个公司 / 哪个组织
artifactId
表示具体的项目或者组件:
xml
<artifactId>spring-boot-starter-web</artifactId>
可以理解成:
具体使用哪个库
version
表示版本:
xml
<version>3.5.0</version>
也就是:
使用哪个版本
所以:
diff
groupId
+
artifactId
+
version
基本可以唯一定位一个 Maven 依赖。
五、Maven 为什么能够自动下载 Jar?
这就涉及:
Repository(仓库)
Maven 世界里最重要的仓库之一是:
Maven Central
你在 pom.xml 中写:
xml
<dependency>
<groupId>xxx</groupId>
<artifactId>xxx</artifactId>
<version>xxx</version>
</dependency>
Maven 就会根据这些信息寻找对应的依赖。
大致过程:
pom.xml
↓
Maven
↓
查找依赖
↓
远程仓库
↓
下载 Jar
↓
本地仓库
↓
项目使用
六、什么是本地仓库?
第一次使用某个依赖时,Maven 通常会从远程仓库下载。
下载之后,会缓存到本地。
例如 Windows 用户通常可以在:
makefile
C:\Users\用户名.m2\repository
看到 Maven 的本地仓库。
里面可能有:
markdown
.m2
└── repository
└── org
└── springframework
└── ...
所以第二次构建项目时,如果本地已经存在对应版本:
Maven
↓
本地仓库有
↓
直接使用
就不需要每次重新下载。
七、Maven 最厉害的地方:传递依赖
假设你的项目依赖:
css
A
但是 A 又依赖:
css
B
B 又依赖:
C
传统方式可能需要你自己一个一个下载:
css
A
B
C
而 Maven 可以自动处理:
css
你的项目
↓
A
↓
B
↓
C
这就是:
传递依赖(Transitive Dependencies)。
所以你只需要声明自己直接需要的依赖,Maven 会根据依赖关系继续解析。
这也是 Maven 依赖管理非常重要的能力之一。(Apache Maven)
八、Maven 的标准项目结构
Maven 最大的特点之一,就是:
约定优于配置。
一个标准 Maven 项目通常是:
css
demo
├── pom.xml
└── src
├── main
│ ├── java
│ └── resources
│
└── test
├── java
└── resources
其中:
css
src/main/java
放业务代码。
css
src/main/resources
放配置文件、资源文件。
bash
src/test/java
放测试代码。
官方 Maven Getting Started Guide 也采用这一标准目录结构。(Apache Maven)
这样做有什么好处?
当你进入一个陌生的 Maven 项目时,不需要重新学习它的目录结构。
看到:
css
src/main/java
基本就知道:
Java 源代码在这里。
这就是 Maven 的:
约定优于配置。
九、Maven Lifecycle 是什么?
这是 Maven 初学者最容易混淆的地方。
经常看到:
bash
mvn clean
mvn compile
mvn test
mvn package
mvn install
这些到底是什么?
可以先简单理解成:
Maven 定义了一套标准的项目构建生命周期。
例如:
bash
validate
↓
compile
↓
test
↓
package
↓
verify
↓
install
↓
deploy
它们代表不同阶段。
十、几个最常用的 Maven 命令
1. clean
mvn clean
主要用于清理之前的构建结果。
例如:
target/
通常会被删除。
可以理解成:
把之前编译产生的东西清理掉。
2. compile
python
mvn compile
编译项目代码。
大概就是:
arduino
.java
↓
.class
3. test
bash
mvn test
编译并运行测试。
4. package
go
mvn package
将项目打包。
例如:
bash
target/demo-1.0.0.jar
或者 Web 项目可能生成:
xxx.war
5. install
mvn install
它不仅会构建项目,还会把生成的构件安装到本地 Maven 仓库。
可以理解成:
bash
项目
↓
编译
↓
测试
↓
打包
↓
安装到 ~/.m2/repository
这样其他本地 Maven 项目就可以引用它。
十一、为什么执行 package 会自动编译和测试?
比如你执行:
go
mvn package
你可能会发现:
bash
compile
test
package
都执行了。
为什么?
因为 Maven 的生命周期阶段是有顺序的。
你执行:
go
mvn package
相当于告诉 Maven:
把项目构建到 package 阶段。
那么 package 前面的必要阶段也会执行。
所以:
go
mvn package
通常不需要你再手动执行:
bash
mvn compile
mvn test
十二、Plugin 又是什么?
Maven 本身并不是把所有事情都硬编码进去。
它大量依赖:
Plugin(插件)。
例如:
编译
测试
打包
生成文档
代码检查
发布
很多能力都是通过插件完成的。
可以简单理解:
Maven
↓
生命周期
↓
插件
↓
具体执行任务
例如编译 Java:
Maven Compiler Plugin
执行测试:
Maven Surefire Plugin
所以 Maven 可以理解成一个:
围绕生命周期、插件和项目模型组织起来的构建系统。
十三、Maven 和 npm 有什么区别?
如果你做过前端,这个对理解 Maven 非常有帮助。
前端:
go
package.json
↓
npm install
↓
node_modules
Java:
bash
pom.xml
↓
mvn package
↓
~/.m2/repository
可以粗略类比:
| 前端 | Java |
|---|---|
| package.json | pom.xml |
| npm | Maven |
| npm install | Maven 下载依赖 |
| node_modules | Maven 本地仓库 |
| package | Jar |
| npm scripts | Maven Plugin / Lifecycle |
当然,这只是帮助理解的类比,两者的构建模型并不完全相同。
十四、Maven 到底解决了什么问题?
如果把 Maven 浓缩成一句话:
Maven 把 Java 项目的构建、依赖、测试、打包和发布流程标准化了。
以前可能是:
css
开发人员 A
自己写构建脚本
开发人员 B
自己管理 Jar
开发人员 C
自己设计项目结构
最后每个项目都不一样。
Maven 希望做到:
markdown
统一项目结构
↓
统一依赖管理
↓
统一构建流程
↓
统一测试流程
↓
统一打包方式
所以当你进入一个新的 Java Maven 项目时,通常只需要先看:
pom.xml
然后执行:
go
mvn clean package
就能快速理解和构建项目。
十五、初学 Maven,真正需要掌握什么?
不要一开始就研究 Maven 几百个配置项。
入门阶段先掌握这几个:
bash
① pom.xml
② groupId / artifactId / version
③ dependency
④ Repository
⑤ 本地仓库 ~/.m2
⑥ Maven 生命周期
⑦ clean / compile / test / package / install
⑧ Plugin
⑨ 传递依赖
⑩ Maven 标准项目结构
把这几个概念搞懂,已经足够应付绝大多数日常 Maven 操作。
十六、最后用一张图理解 Maven
可以把 Maven 想象成:
markdown
Maven
│
┌───────────┼───────────┐
↓ ↓ ↓
POM Lifecycle Repository
│ │ │
↓ ↓ ↓
依赖配置 构建流程 下载依赖
│ │ │
└───────────┼───────────┘
↓
Plugin
↓
编译 / 测试 / 打包
↓
Jar / War
所以 Maven 并不只是:
"Java 的依赖管理工具。"
更准确的理解是:
Maven 是一个以 POM 为核心,通过依赖管理、生命周期和插件来标准化 Java 项目构建与管理的工具。