Maven :Java 项目中的“项目管家、依赖管理器、构建工具”
一、Maven 是什么?
在 Java 开发中,Maven 是一个非常重要的工具。
它不是 Java 语法,也不是 JDK 的一部分,而是一个专门用来管理 Java 项目的工具。
简单来说,Maven 主要做三件事:
-
管理依赖
-
统一项目结构
-
自动构建项目
如果用一句话概括:
Maven 是 Java 项目的“项目管家”,它可以帮我们自动下载第三方 jar 包、管理项目结构、编译代码、运行测试、打包项目。
二、为什么 Java 项目需要 Maven?
在没有 Maven 之前,Java 项目经常会遇到这些问题:
1. 项目需要很多第三方 jar 包,需要手动下载。
2. jar 包之间还有依赖关系,一个 jar 又依赖另一个 jar。
3. jar 包版本容易冲突。
4. 不同人电脑上的项目结构不统一。
5. 项目打包过程复杂。
6. 换一台电脑之后,项目可能跑不起来。
7. 团队协作时,不知道别人到底用了哪些依赖。
比如我们做一个 Java Web 项目,可能需要:
Spring Boot
Spring MVC
MyBatis
MySQL Driver
Lombok
Jackson
JUnit
Logback
Redis Client
Swagger
如果没有 Maven,我们可能要自己一个个去网上下载 jar 包,然后手动导入项目。
这样做非常麻烦,而且很容易出错。
有了 Maven 之后,我们只需要在 pom.xml 文件中写清楚需要什么依赖,Maven 就会自动帮我们下载。
例如:
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<version>8.4.0</version>
</dependency>
这段配置的意思是:
当前项目需要使用 MySQL 驱动,版本是 8.4.0。
然后 Maven 会自动下载对应的 jar 包,并把它加入到项目中。
三、Maven 在 Java 体系中的位置
很多初学者容易把 JDK、IDEA、Maven、Spring Boot 混在一起。
它们的关系可以这样理解:
| 名称 | 作用 |
|---|---|
| JDK | Java 开发工具包,负责编译和运行 Java 程序 |
| IDEA | Java 开发工具,用来写代码、运行项目、调试程序 |
| Maven | 项目管理和构建工具,负责依赖下载、编译、测试、打包 |
| Spring Boot | Java 后端开发框架,用来快速开发 Web 后端项目 |
| pom.xml | Maven 项目的核心配置文件 |
可以用一个比喻来理解:
JDK = 厨具和灶台
Java 代码 = 食材
第三方 jar 包 = 调料
pom.xml = 菜谱
Maven = 按菜谱自动准备调料、处理食材、完成打包的人
IDEA = 厨房工作台
Spring Boot = 一套成熟的做菜方案
所以 Maven 的本质不是写业务代码,而是管理项目。
四、Maven 的核心作用
1. 依赖管理
Maven 最重要的作用之一就是依赖管理。
什么是依赖?
简单说:
你的项目需要使用别人写好的代码库,这些代码库就是依赖。
比如你要连接 MySQL 数据库,就需要 MySQL 驱动。
你要开发 Web 接口,就需要 Spring Web。
你要写单元测试,就需要 JUnit。
这些都属于项目依赖。
在 Maven 中,依赖写在 pom.xml 文件中:
<dependencies>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<version>8.4.0</version>
</dependency>
</dependencies>
Maven 看到这段配置后,会自动去远程仓库下载 jar 包。
2. 统一项目结构
Maven 对项目结构有一套默认规范。
一个标准 Maven 项目通常长这样:
my-project
├── pom.xml
└── src
├── main
│ ├── java
│ │ └── com/example
│ │ └── Main.java
│ └── resources
│ └── application.yml
└── test
└── java
└── com/example
└── MainTest.java
各目录含义如下:
| 路径 | 作用 |
|---|---|
pom.xml |
Maven 项目的核心配置文件 |
src/main/java |
存放正式 Java 源代码 |
src/main/resources |
存放配置文件、静态资源等 |
src/test/java |
存放测试代码 |
src/test/resources |
存放测试相关资源 |
target |
Maven 编译和打包后的输出目录 |
例如 Spring Boot 项目中常见:
src/main/resources/application.yml
这个文件通常用来配置数据库、端口号、Redis、日志等信息。
3. 项目构建
所谓构建,不只是运行项目。
构建包括:
清理旧文件
编译源代码
处理资源文件
运行测试
打包 jar 或 war
安装到本地仓库
部署到远程仓库
Maven 可以通过命令完成这些操作。
常见命令如下:
mvn clean
清理旧的构建结果,也就是删除 target 目录。
mvn compile
编译项目源代码。
mvn test
运行测试代码。
mvn package
将项目打包成 jar 或 war。
mvn install
将当前项目打包后安装到本地 Maven 仓库。
mvn deploy
将项目发布到远程仓库,通常用于公司内部公共模块发布。
五、Maven 工作流程图
下面用 Mermaid 画一个 Maven 的基本工作流程。
flowchart TD
A[开发者编写 Java 代码] --> B[配置 pom.xml]
B --> C[执行 Maven 命令]
C --> D{本地仓库是否已有依赖?}
D -- 有 --> E[直接使用本地依赖]
D -- 没有 --> F[从远程仓库下载依赖]
F --> G[保存到本地仓库]
E --> H[编译源代码]
G --> H
H --> I[运行测试]
I --> J[打包 jar/war]
J --> K[生成 target 目录]
六、Maven 的核心文件:pom.xml
1. 什么是 pom.xml?
Maven 项目最重要的文件就是:
pom.xml
POM 是:
Project Object Model
项目对象模型
你可以把 pom.xml 理解成 Maven 项目的说明书。
它告诉 Maven:
这个项目叫什么?
这个项目属于谁?
这个项目是什么版本?
这个项目需要哪些依赖?
这个项目用哪个 JDK 编译?
这个项目如何打包?
这个项目需要哪些插件?
2. 最简单的 pom.xml
一个最基础的 Maven 项目 pom.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
https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>demo</artifactId>
<version>1.0-SNAPSHOT</version>
</project>
3. groupId、artifactId、version 是什么?
Maven 中最重要的三个坐标是:
groupId
artifactId
version
它们合起来叫做 Maven 坐标。
也叫 GAV 坐标。
G = groupId
A = artifactId
V = version
一个依赖可以通过这三个坐标唯一确定。
4. groupId
groupId 通常表示组织、公司、团队或者个人。
一般使用域名反写。
例如:
<groupId>com.example</groupId>
如果公司域名是:
example.com
那么 groupId 通常写成:
com.example
个人项目可以写:
<groupId>com.memoryleak</groupId>
5. artifactId
artifactId 表示项目名称或者模块名称。
例如:
<artifactId>student-management-system</artifactId>
它代表当前项目叫:
student-management-system
6. version
version 表示项目版本。
例如:
<version>1.0-SNAPSHOT</version>
其中:
1.0 表示版本号
SNAPSHOT 表示快照版本,也就是开发中的版本
常见版本形式:
1.0-SNAPSHOT 开发版
1.0.0 正式版
2.1.3 正式迭代版本
7. Maven 坐标示意图
flowchart LR
A[Maven 坐标] --> B[groupId<br/>组织或公司]
A --> C[artifactId<br/>项目或模块名]
A --> D[version<br/>版本号]
B --> E[com.example]
C --> F[demo]
D --> G[1.0-SNAPSHOT]
七、Maven 依赖详解
1. dependencies 标签
所有依赖通常写在:
<dependencies>
</dependencies>
里面。
例如:
<dependencies>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<version>8.4.0</version>
</dependency>
</dependencies>
2. dependency 标签
每一个 <dependency> 代表一个依赖。
一个完整依赖通常包含:
<dependency>
<groupId>依赖所属组织</groupId>
<artifactId>依赖名称</artifactId>
<version>依赖版本</version>
<scope>依赖作用范围</scope>
</dependency>
其中 scope 可以不写,不写时默认是 compile。
八、Maven 依赖下载过程
当我们添加一个依赖后,Maven 的查找顺序大概是:
1. 先查找本地仓库
2. 如果本地仓库没有,就去远程仓库下载
3. 下载成功后保存到本地仓库
4. 当前项目使用本地仓库中的依赖
流程图如下:
flowchart TD
A[项目 pom.xml 中声明依赖] --> B[Maven 开始解析依赖]
B --> C{本地仓库是否存在?}
C -- 存在 --> D[直接使用本地仓库中的 jar]
C -- 不存在 --> E[访问远程仓库]
E --> F{远程仓库是否存在?}
F -- 存在 --> G[下载 jar 和 pom 文件]
G --> H[保存到本地仓库]
H --> D
F -- 不存在 --> I[报错: Could not find artifact]
九、Maven 仓库
Maven 仓库用来存放 jar 包、插件、项目构件。
Maven 仓库主要分为三类:
本地仓库
中央仓库
私服仓库
1. 本地仓库
本地仓库就是你电脑上的 Maven 缓存目录。
Windows 默认位置:
C:\Users\你的用户名\.m2\repository
例如:
C:\Users\MemoryLeak\.m2\repository
Linux 或 macOS 默认位置:
~/.m2/repository
当 Maven 第一次下载某个依赖时,会把它保存到本地仓库。
以后如果其他项目也使用同一个依赖,Maven 就不用再次下载,而是直接使用本地仓库中的文件。
2. 中央仓库
中央仓库是 Maven 默认使用的公共远程仓库。
大量常见 Java 依赖都可以从中央仓库下载,例如:
Spring Boot
MyBatis
MySQL Driver
JUnit
Lombok
Jackson
Logback
Apache Commons
3. 私服仓库
私服仓库通常是公司内部搭建的 Maven 仓库。
常见工具有:
Nexus
Artifactory
公司使用私服仓库的原因:
1. 提高依赖下载速度
2. 统一管理公司内部 jar 包
3. 避免每个人都访问外网仓库
4. 控制依赖版本
5. 提高构建稳定性
4. 仓库关系图
flowchart TD
A[Java 项目] --> B[Maven]
B --> C[本地仓库 ~/.m2/repository]
C --> D{依赖是否存在?}
D -- 存在 --> E[使用本地依赖]
D -- 不存在 --> F[远程仓库]
F --> G[中央仓库 Maven Central]
F --> H[公司私服 Nexus/Artifactory]
G --> I[下载到本地仓库]
H --> I
I --> E
十、Maven 本地仓库目录长什么样?
比如有一个依赖:
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<version>8.4.0</version>
</dependency>
它在本地仓库中大致会变成:
.m2/repository
└── com
└── mysql
└── mysql-connector-j
└── 8.4.0
├── mysql-connector-j-8.4.0.jar
├── mysql-connector-j-8.4.0.pom
└── _remote.repositories
注意:
groupId 中的点号会变成目录层级
com.mysql -> com/mysql
十一、Maven 配置文件 settings.xml
除了项目里的 pom.xml,Maven 还有一个全局或用户级配置文件:
settings.xml
常见位置:
Maven安装目录/conf/settings.xml
或者:
C:\Users\你的用户名\.m2\settings.xml
Linux/macOS:
~/.m2/settings.xml
1. settings.xml 和 pom.xml 的区别
| 文件 | 作用 |
|---|---|
pom.xml |
描述当前项目的依赖、插件、构建方式 |
settings.xml |
描述 Maven 自身配置,例如本地仓库位置、镜像、私服账号 |
简单说:
pom.xml 管项目
settings.xml 管 Maven 自己
2. 配置本地仓库位置
默认本地仓库在:
C:\Users\用户名\.m2\repository
如果你想改到 D 盘,可以在 settings.xml 中配置:
<settings>
<localRepository>D:\MavenRepository</localRepository>
</settings>
这样 Maven 下载的 jar 包就会放到:
D:\MavenRepository
3. 配置国内镜像
如果下载依赖很慢,可以配置国内镜像。
示例:
<settings>
<mirrors>
<mirror>
<id>aliyunmaven</id>
<mirrorOf>central</mirrorOf>
<name>阿里云公共仓库</name>
<url>https://maven.aliyun.com/repository/public</url>
</mirror>
</mirrors>
</settings>
含义:
| 标签 | 作用 |
|---|---|
id |
镜像 ID |
mirrorOf |
替代哪个仓库 |
name |
镜像名称 |
url |
镜像地址 |
十二、Maven 生命周期
Maven 的构建不是随便执行的,它有固定的生命周期。
Maven 内置三个生命周期:
clean
default
site
1. clean 生命周期
clean 生命周期负责清理项目。
最常见命令:
mvn clean
它会删除 target 目录。
2. default 生命周期
default 是最常用的生命周期,负责项目的主要构建流程。
常见阶段如下:
validate
compile
test
package
verify
install
deploy
解释如下:
| 阶段 | 作用 |
|---|---|
| validate | 验证项目是否正确 |
| compile | 编译主代码 |
| test | 运行测试代码 |
| package | 打包成 jar 或 war |
| verify | 检查包是否有效 |
| install | 安装到本地仓库 |
| deploy | 发布到远程仓库 |
3. site 生命周期
site 生命周期用于生成项目站点文档。
常见命令:
mvn site
普通学习和一般业务开发中较少使用。
十三、生命周期执行顺序
Maven 生命周期有一个非常重要的特点:
执行后面的阶段时,前面的阶段会自动执行。
例如:
mvn package
并不是只执行 package。
它会先执行:
validate -> compile -> test -> package
再比如:
mvn install
会执行:
validate -> compile -> test -> package -> verify -> install
流程图如下:
flowchart LR
A[validate] --> B[compile]
B --> C[test]
C --> D[package]
D --> E[verify]
E --> F[install]
F --> G[deploy]
所以如果你执行:
mvn package
Maven 会从 validate 一直执行到 package。
如果你执行:
mvn install
Maven 会从 validate 一直执行到 install。
十四、常用 Maven 命令详解
1. mvn clean
mvn clean
作用:
删除 target 目录,清理旧的编译结果。
适用场景:
1. 项目编译异常
2. target 中存在旧文件
3. 想重新完整构建项目
2. mvn compile
mvn compile
作用:
编译 src/main/java 中的代码。
编译结果会放在:
target/classes
3. mvn test
mvn test
作用:
编译并运行 src/test/java 中的测试代码。
4. mvn package
mvn package
作用:
将项目打包成 jar 或 war。
打包结果通常在:
target/项目名-版本号.jar
例如:
target/demo-1.0-SNAPSHOT.jar
5. mvn install
mvn install
作用:
把当前项目打包,并安装到本地 Maven 仓库。
什么时候用?
当你的项目 A 需要被另一个项目 B 引用时,可以先在项目 A 中执行:
mvn install
然后项目 B 就可以通过 Maven 坐标引用项目 A。
6. mvn deploy
mvn deploy
作用:
把项目发布到远程仓库。
一般公司内部公共模块、SDK、工具包会用到。
普通初学者不常用。
7. 跳过测试打包
有时测试代码有问题,但你想先打包,可以用:
mvn package -DskipTests
这个命令会跳过测试运行,但可能仍然编译测试代码。
如果连测试代码编译也想跳过,可以用:
mvn package -Dmaven.test.skip=true
区别:
| 命令 | 作用 |
|---|---|
-DskipTests |
跳过测试运行,但可能编译测试代码 |
-Dmaven.test.skip=true |
跳过测试编译和测试运行 |
8. 查看依赖树
mvn dependency:tree
作用:
查看当前项目的完整依赖关系。
这个命令在排查依赖冲突时非常有用。
例如你发现项目中有多个版本的日志包,就可以通过依赖树查看是谁引入的。
9. 强制更新依赖
mvn clean package -U
-U 的作用是强制更新依赖。
适用场景:
1. SNAPSHOT 版本依赖更新了
2. 本地依赖缓存异常
3. 远程仓库依赖变动后本地没有刷新
十五、Maven 插件
Maven 的很多功能其实不是 Maven 本体直接完成的,而是通过插件完成的。
比如:
| 功能 | 插件 |
|---|---|
| 编译 Java 代码 | maven-compiler-plugin |
| 运行测试 | maven-surefire-plugin |
| 打包 jar | maven-jar-plugin |
| 打包 war | maven-war-plugin |
| 清理 target | maven-clean-plugin |
| 生成源码包 | maven-source-plugin |
| Spring Boot 打包 | spring-boot-maven-plugin |
1. maven-compiler-plugin
这个插件用来配置 Java 编译版本。
例如:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.13.0</version>
<configuration>
<source>24</source>
<target>24</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
</plugins>
</build>
含义:
source = 使用 Java 24 语法编译
target = 生成 Java 24 版本字节码
encoding = 使用 UTF-8 编码
也可以在 properties 中写:
<properties>
<maven.compiler.source>24</maven.compiler.source>
<maven.compiler.target>24</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
2. spring-boot-maven-plugin
Spring Boot 项目通常会有:
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
作用:
把 Spring Boot 项目打包成可直接运行的 jar 包。
普通 jar 包可能不能直接运行,而 Spring Boot 打包后的 jar 包可以通过:
java -jar demo.jar
直接运行。
十六、Maven 生命周期、阶段、插件、目标之间的关系
这是 Maven 比较容易混乱的地方。
先看几个概念:
| 概念 | 英文 | 含义 |
|---|---|---|
| 生命周期 | lifecycle | 一套构建流程 |
| 阶段 | phase | 生命周期中的某一步 |
| 插件 | plugin | 真正执行任务的工具 |
| 目标 | goal | 插件中的具体任务 |
举例:
mvn compile
这里的 compile 是生命周期中的一个阶段。
Maven 执行到 compile 阶段时,会调用编译插件的某个目标来完成编译。
再比如:
mvn dependency:tree
这里的:
dependency = 插件
tree = 插件目标
它的意思是执行 Maven Dependency Plugin 插件中的 tree 目标,用来打印依赖树。
关系图
flowchart TD
A[生命周期 Lifecycle] --> B[阶段 Phase]
B --> C[插件 Plugin]
C --> D[目标 Goal]
D --> E[具体任务: 编译/测试/打包/清理]
十七、Maven 依赖范围 scope
Maven 依赖中有一个重要配置:
<scope>...</scope>
它表示依赖在什么时候生效。
常见 scope 有:
compile
provided
runtime
test
system
import
1. compile
默认值。
如果不写 scope,默认就是 compile。
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.14.0</version>
</dependency>
等价于:
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.14.0</version>
<scope>compile</scope>
</dependency>
特点:
编译时需要
运行时需要
测试时需要
会被打包传播
常见依赖:
工具类库
业务代码依赖库
Spring 核心库
2. provided
provided 表示编译时需要,但运行时由外部环境提供。
典型例子:
<dependency>
<groupId>jakarta.servlet</groupId>
<artifactId>jakarta.servlet-api</artifactId>
<version>6.0.0</version>
<scope>provided</scope>
</dependency>
含义:
编译代码时需要 Servlet API
但真正运行时 Tomcat 容器会提供它
所以打包时不需要把它打进去
常见场景:
Servlet API
某些应用服务器提供的依赖
3. runtime
runtime 表示编译时不需要,运行时需要。
典型例子:
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<version>8.4.0</version>
<scope>runtime</scope>
</dependency>
例如 JDBC 编程时,代码里主要依赖 JDBC 接口,而 MySQL 驱动在运行时才真正发挥作用。
4. test
test 表示只在测试时使用。
典型例子:
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.10.2</version>
<scope>test</scope>
</dependency>
特点:
主代码不能使用
测试代码可以使用
不会被打包到正式项目中
5. system
system 表示手动指定本地 jar 路径。
不推荐使用。
示例:
<dependency>
<groupId>com.example</groupId>
<artifactId>local-lib</artifactId>
<version>1.0</version>
<scope>system</scope>
<systemPath>${project.basedir}/libs/local-lib.jar</systemPath>
</dependency>
缺点:
依赖路径写死
不利于团队协作
不利于跨平台
不利于构建稳定
一般不建议这样做。
6. scope 总结表
| scope | 编译主代码 | 运行主程序 | 编译测试 | 运行测试 | 是否打包 |
|---|---|---|---|---|---|
| compile | 是 | 是 | 是 | 是 | 是 |
| provided | 是 | 否 | 是 | 是 | 否 |
| runtime | 否 | 是 | 是 | 是 | 是 |
| test | 否 | 否 | 是 | 是 | 否 |
| system | 是 | 是 | 是 | 是 | 不推荐 |
十八、Maven 依赖传递
Maven 有一个非常重要的功能:
依赖可以传递。
什么意思?
假设:
你的项目 A 依赖 B
B 又依赖 C
那么 Maven 会自动把 C 也引入进来。
也就是:
A -> B -> C
只要你引入 B,C 也会被 Maven 自动引入。
流程图如下:
flowchart LR
A[项目 A] --> B[依赖 B]
B --> C[依赖 C]
C --> D[依赖 D]
这种间接依赖叫做:
传递依赖
十九、依赖冲突
依赖传递虽然方便,但也会带来依赖冲突问题。
例如:
项目 A 依赖 B 和 C
B 依赖 logback 1.2.0
C 依赖 logback 1.4.0
那么项目里到底使用哪个版本?
Maven 有自己的依赖调解规则。
常见规则:
1. 路径最近者优先
2. 路径相同则先声明者优先
1. 路径最近者优先
例如:
项目 A -> B -> D 1.0
项目 A -> C -> E -> D 2.0
D 1.0 距离项目 A 更近,所以 Maven 可能选择 D 1.0。
图示:
flowchart TD
A[项目 A] --> B[依赖 B]
A --> C[依赖 C]
B --> D1[D 1.0<br/>距离更近]
C --> E[依赖 E]
E --> D2[D 2.0<br/>距离更远]
2. 路径相同则先声明者优先
如果两个版本路径深度一样,那么谁在 pom.xml 中先声明,谁优先。
3. 查看依赖冲突
可以使用:
mvn dependency:tree
也可以输出到文件:
mvn dependency:tree -DoutputFile=dependency-tree.txt
4. 排除传递依赖
如果你不想引入某个传递依赖,可以使用 exclusions。
例如:
<dependency>
<groupId>com.example</groupId>
<artifactId>some-library</artifactId>
<version>1.0.0</version>
<exclusions>
<exclusion>
<groupId>com.example</groupId>
<artifactId>bad-library</artifactId>
</exclusion>
</exclusions>
</dependency>
含义:
引入 some-library
但是排除它传递进来的 bad-library
二十、dependencyManagement
dependencyManagement 是 Maven 中非常重要但容易误解的标签。
它的作用是:
统一管理依赖版本,但不会真正引入依赖。
例如父工程中写:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<version>8.4.0</version>
</dependency>
</dependencies>
</dependencyManagement>
这并不代表当前项目已经引入了 MySQL 驱动。
子模块真正使用时还要写:
<dependencies>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
</dependency>
</dependencies>
注意这里可以不写 version,因为版本已经由父工程统一管理。
dependencyManagement 和 dependencies 的区别
| 标签 | 作用 | 是否真正引入依赖 |
|---|---|---|
dependencies |
声明项目实际使用的依赖 | 是 |
dependencyManagement |
管理依赖版本 | 否 |
简单记忆:
dependencies = 真正买东西
dependencyManagement = 只写购物清单价格标准
二十一、Maven 父工程
在大型项目中,通常会有父工程。
父工程常用来统一管理:
1. JDK 版本
2. 编码格式
3. Spring Boot 版本
4. 第三方依赖版本
5. Maven 插件版本
6. 子模块列表
父工程通常是:
<packaging>pom</packaging>
示例:
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>my-parent</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<modules>
<module>user-service</module>
<module>order-service</module>
</modules>
</project>
二十二、Maven 多模块项目
多模块项目就是一个父工程下面包含多个子模块。
例如:
my-system
├── pom.xml
├── common
│ └── pom.xml
├── user-service
│ └── pom.xml
└── order-service
└── pom.xml
含义:
| 模块 | 作用 |
|---|---|
my-system |
父工程,统一管理版本和模块 |
common |
公共工具模块 |
user-service |
用户模块 |
order-service |
订单模块 |
多模块关系图
flowchart TD
A[父工程 my-system] --> B[common 公共模块]
A --> C[user-service 用户模块]
A --> D[order-service 订单模块]
C --> B
D --> B
如果 user-service 想使用 common,可以在 user-service/pom.xml 中写:
<dependency>
<groupId>com.example</groupId>
<artifactId>common</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
二十三、packaging 打包类型
Maven 中可以通过 packaging 指定打包方式。
常见类型:
| packaging | 含义 |
|---|---|
jar |
普通 Java 项目,打成 jar 包 |
war |
Java Web 项目,打成 war 包 |
pom |
父工程,不打包代码,只管理模块和配置 |
如果不写,默认是:
<packaging>jar</packaging>
父工程通常写:
<packaging>pom</packaging>
Web 项目可能写:
<packaging>war</packaging>
二十四、Maven 和 Spring Boot
Spring Boot 项目通常使用 Maven 管理依赖。
一个典型 Spring Boot 项目 pom.xml 如下:
<project>
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.0</version>
<relativePath/>
</parent>
<groupId>com.example</groupId>
<artifactId>springboot-demo</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<!-- Spring Web 依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- MySQL 驱动 -->
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
<!-- 测试依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<!-- Spring Boot 打包插件 -->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
二十五、starter 是什么?
Spring Boot 里经常看到:
<artifactId>spring-boot-starter-web</artifactId>
这里的 starter 可以理解成:
一组依赖的集合。
比如 spring-boot-starter-web 会帮你引入开发 Web 所需要的一组依赖。
你不需要手动一个个引入:
Spring MVC
Tomcat
Jackson
Validation
日志组件
Spring Boot starter 帮你打包管理好了。
二十六、Maven 和 JDK 版本
Maven 构建 Java 项目时,需要调用 JDK。
也就是说:
Maven 自己不编译 Java
真正编译 Java 的是 JDK 中的 javac
Maven 只是组织构建流程
因此 Maven 使用哪个 JDK 非常重要。
比如你的 pom.xml 写:
<properties>
<maven.compiler.source>24</maven.compiler.source>
<maven.compiler.target>24</maven.compiler.target>
</properties>
意思是:
使用 Java 24 语法编译
生成 Java 24 字节码
如果 Maven 实际使用的是 JDK 17,就可能报错。
常见错误类似:
invalid target release: 24
原因就是:
Maven 当前使用的 JDK 版本太低,不支持 target 24
二十七、IDEA 中 Maven 和 JDK 的关系
在 IDEA 中,至少有几个位置和 JDK 有关:
1. Project SDK
2. Module SDK
3. Maven Runner JRE
4. pom.xml 中的 source/target
它们最好保持一致。
例如你项目使用 Java 24,那么建议:
Project SDK = JDK 24
Module SDK = JDK 24
Maven Runner JRE = JDK 24
pom.xml source/target = 24
否则就容易出现:
IDEA 能运行
Maven 打包失败
或者:
Maven 能编译
IDEA 代码提示异常
二十八、Maven Wrapper
Maven Wrapper 是什么?
它可以理解成:
项目自带的 Maven 启动器。
普通 Maven 命令:
mvn clean package
使用 Maven Wrapper:
Windows:
mvnw.cmd clean package
Linux/macOS:
./mvnw clean package
Maven Wrapper 有什么用?
Maven Wrapper 的好处:
1. 不要求使用者提前安装 Maven
2. 可以让团队使用同一个 Maven 版本
3. 避免“我电脑能跑,你电脑不能跑”
4. 适合开源项目和团队项目
但是要注意:
Maven Wrapper 能帮你管理 Maven 版本,但不能替你安装 JDK。
也就是说,你仍然需要正确安装 JDK。
Maven Wrapper 项目结构
使用 Maven Wrapper 的项目通常会多出这些文件:
my-project
├── mvnw
├── mvnw.cmd
├── .mvn
│ └── wrapper
│ └── maven-wrapper.properties
├── pom.xml
└── src
其中:
| 文件 | 作用 |
|---|---|
mvnw |
Linux/macOS 下使用的 Maven Wrapper 脚本 |
mvnw.cmd |
Windows 下使用的 Maven Wrapper 脚本 |
.mvn/wrapper/maven-wrapper.properties |
指定 Maven Wrapper 下载哪个 Maven 版本 |
二十九、Maven 和 Gradle 的区别
Java 项目常见构建工具有:
Maven
Gradle
对比如下:
| 对比项 | Maven | Gradle |
|---|---|---|
| 配置文件 | XML | Groovy/Kotlin DSL |
| 学习难度 | 较低 | 较高 |
| 规则 | 约定强、规范统一 | 灵活度高 |
| 构建速度 | 一般 | 通常更快 |
| 常见场景 | Java 后端、传统企业项目 | Android、大型复杂项目 |
| 初学推荐 | 推荐 | 后期再学 |
对于 Java 后端初学者,建议先掌握 Maven。
因为 Spring Boot、MyBatis、企业后端项目中 Maven 非常常见。
三十、完整 pom.xml 示例:普通 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
https://maven.apache.org/xsd/maven-4.0.0.xsd">
<!-- POM 模型版本,固定写 4.0.0 -->
<modelVersion>4.0.0</modelVersion>
<!-- 项目坐标 -->
<groupId>com.example</groupId>
<artifactId>maven-demo</artifactId>
<version>1.0-SNAPSHOT</version>
<!-- 打包方式,默认 jar -->
<packaging>jar</packaging>
<!-- 项目属性 -->
<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>
<!-- Apache Commons Lang 工具包 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.14.0</version>
</dependency>
<!-- JUnit 测试框架 -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.10.2</version>
<scope>test</scope>
</dependency>
</dependencies>
<!-- 构建配置 -->
<build>
<plugins>
<!-- Java 编译插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.13.0</version>
<configuration>
<source>17</source>
<target>17</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
</plugins>
</build>
</project>
三十一、完整 pom.xml 示例:Spring Boot 项目
<?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
https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<!-- Spring Boot 父工程 -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.0</version>
<relativePath/>
</parent>
<!-- 当前项目坐标 -->
<groupId>com.example</groupId>
<artifactId>springboot-maven-demo</artifactId>
<version>1.0-SNAPSHOT</version>
<!-- 项目属性 -->
<properties>
<java.version>17</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<!-- 依赖 -->
<dependencies>
<!-- Web 开发依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- MySQL 驱动 -->
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
<!-- Lombok,简化实体类代码 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!-- 测试依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<!-- 构建插件 -->
<build>
<plugins>
<!-- Spring Boot 打包插件 -->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
三十二、常见 Maven 报错与解决方法
1. Could not find artifact
错误示例:
Could not find artifact com.example:xxx:jar:1.0
原因可能是:
1. 依赖坐标写错了
2. 版本号不存在
3. 远程仓库没有这个依赖
4. 网络无法访问 Maven 仓库
5. 公司私服没有配置
解决方法:
1. 检查 groupId、artifactId、version 是否正确
2. 检查网络
3. 配置国内镜像
4. 如果是本地模块,先执行 mvn install
2. invalid target release
错误示例:
invalid target release: 24
原因:
pom.xml 中配置了 Java 24
但 Maven 实际使用的 JDK 版本低于 24
解决:
1. 安装 JDK 24
2. 配置 JAVA_HOME 指向 JDK 24
3. IDEA 中 Maven Runner JRE 选择 JDK 24
4. 确认命令行 java -version 和 mvn -version
检查命令:
java -version
mvn -version
重点看:
mvn -version 中显示的 Java version
3. Dependency not found
IDEA 中依赖标红,通常原因:
1. Maven 没刷新
2. 依赖没下载成功
3. 本地仓库缓存损坏
4. settings.xml 配置错误
5. 网络问题
解决:
1. 点击 IDEA Maven 面板 Reload All Maven Projects
2. 执行 mvn clean package -U
3. 删除本地仓库中对应依赖目录后重新下载
4. 检查 settings.xml
4. 编码乱码
如果项目中出现中文乱码,可以在 pom.xml 中配置:
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
</properties>
同时 IDEA 中也建议设置:
File Encoding = UTF-8
5. 程序包 xxx 不存在
错误示例:
程序包 org.springframework.web.bind.annotation 不存在
原因:
1. 依赖没有引入
2. Maven 没刷新
3. 依赖下载失败
4. 代码 import 错误
解决:
1. 检查 pom.xml 是否添加相关依赖
2. 刷新 Maven
3. 执行 mvn clean compile
4. 查看 External Libraries 是否存在对应 jar
三十三、Maven 学习路线
如果你是 Java 初学者,建议按这个顺序学习 Maven:
第一阶段:理解 Maven 是什么
第二阶段:掌握 pom.xml 基本结构
第三阶段:会添加 dependency
第四阶段:理解本地仓库和远程仓库
第五阶段:会使用常用命令 clean/compile/package/install
第六阶段:理解生命周期
第七阶段:理解 scope
第八阶段:会查看 dependency:tree
第九阶段:理解 dependencyManagement
第十阶段:能看懂 Spring Boot 项目的 pom.xml
第十一阶段:理解父工程和多模块
第十二阶段:掌握 Maven Wrapper
三十四、Maven 学习路线图
flowchart TD
A[认识 Maven] --> B[理解 pom.xml]
B --> C[掌握 GAV 坐标]
C --> D[添加 dependencies]
D --> E[理解本地仓库和远程仓库]
E --> F[掌握常用 Maven 命令]
F --> G[理解生命周期]
G --> H[理解插件和目标]
H --> I[掌握 scope]
I --> J[排查依赖冲突]
J --> K[理解 dependencyManagement]
K --> L[掌握父工程和多模块]
L --> M[理解 Spring Boot Maven 项目]
M --> N[掌握 Maven Wrapper]
三十五、Maven 面试常见问题
1. Maven 是什么?
Maven 是一个项目管理和构建工具,主要用于 Java 项目。它可以通过 pom.xml 管理项目依赖、统一项目结构、执行编译、测试、打包、安装、部署等构建流程。
2. Maven 的核心作用是什么?
主要有三个:
1. 依赖管理
2. 项目构建
3. 项目信息管理
具体包括:
下载第三方 jar 包
管理依赖版本
统一项目目录结构
编译代码
运行测试
打包项目
发布项目
3. pom.xml 是什么?
pom.xml 是 Maven 项目的核心配置文件。
它用于描述:
项目坐标
项目依赖
构建插件
打包方式
父工程
子模块
仓库配置
编译版本
4. Maven 坐标是什么?
Maven 坐标由三部分组成:
groupId
artifactId
version
例如:
<groupId>com.example</groupId>
<artifactId>demo</artifactId>
<version>1.0-SNAPSHOT</version>
它们可以唯一定位一个 Maven 构件。
5. Maven 生命周期有哪些?
Maven 内置三个生命周期:
clean
default
site
其中 default 生命周期最常用,包含:
validate
compile
test
package
verify
install
deploy
6. mvn package 和 mvn install 的区别是什么?
mvn package:
将项目打包,生成 jar 或 war,结果在 target 目录下。
mvn install:
不仅会打包,还会把打包结果安装到本地 Maven 仓库。
也就是说:
install 包含 package 的过程。
7. dependencyManagement 和 dependencies 的区别是什么?
dependencies:
真正引入依赖。
dependencyManagement:
只管理依赖版本,不真正引入依赖。
子模块如果要使用某个依赖,仍然需要在 dependencies 中声明。
8. Maven 如何解决依赖冲突?
Maven 常见依赖调解规则:
1. 路径最近者优先
2. 路径相同则先声明者优先
可以通过:
mvn dependency:tree
查看依赖树,分析冲突来源。
9. Maven scope 有哪些?
常见 scope:
compile
provided
runtime
test
system
import
最常用的是:
| scope | 含义 |
|---|---|
| compile | 默认,编译和运行都需要 |
| provided | 编译需要,运行环境提供 |
| runtime | 编译不需要,运行需要 |
| test | 只在测试时使用 |
10. Maven Wrapper 是什么?
Maven Wrapper 是项目自带的 Maven 启动脚本。
它可以让项目使用指定版本的 Maven,而不要求开发者提前全局安装 Maven。
Windows 下使用:
mvnw.cmd clean package
Linux/macOS 下使用:
./mvnw clean package
三十六、适合初学者的 Maven 实战步骤
第一步:创建 Maven 项目
项目结构:
maven-demo
├── pom.xml
└── src
└── main
└── java
└── com
└── example
└── Main.java
第二步:编写 Main.java
package com.example;
public class Main {
public static void main(String[] args) {
System.out.println("Hello Maven!");
}
}
第三步:编写 pom.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
https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>maven-demo</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
</project>
第四步:执行编译
mvn compile
成功后会生成:
target/classes/com/example/Main.class
第五步:执行打包
mvn package
成功后会生成:
target/maven-demo-1.0-SNAPSHOT.jar
三十七、Maven 最重要的几个记忆点
初学者只要先记住这些:
1. Maven 是 Java 项目的构建和依赖管理工具。
2. Maven 项目的核心文件是 pom.xml。
3. Maven 通过 groupId、artifactId、version 定位依赖。
4. Maven 会先查本地仓库,没有再去远程仓库下载。
5. Maven 默认本地仓库在 ~/.m2/repository。
6. Maven 生命周期包括 clean、default、site。
7. mvn package 会打包项目。
8. mvn install 会把项目安装到本地仓库。
9. dependencies 是真正引入依赖。
10. dependencyManagement 只是统一管理版本。
11. Maven 插件负责真正执行编译、测试、打包等任务。
12. Spring Boot 项目通常使用 Maven 管理依赖和打包。
三十八、总结
Maven 是 Java 开发中非常基础也非常重要的工具。
对于初学者来说,不要一开始就陷入复杂配置,而应该先掌握它的主线:
pom.xml 写项目配置
dependencies 管理依赖
repository 存放依赖
lifecycle 组织构建流程
plugin 执行具体任务
package/install 完成打包和安装
只要理解了这条主线,再去看 Spring Boot 项目的 pom.xml,就不会觉得它是一堆看不懂的 XML 标签。
最后用一句话总结 Maven:
Maven 就是 Java 项目的自动化管家:它按照 pom.xml 这份说明书,帮我们下载依赖、管理版本、编译代码、运行测试、打包项目,让 Java 项目开发更加规范、稳定、可复现。
更多推荐



所有评论(0)