Maven 到底是什么?一篇文章搞懂 Java 项目构建与依赖管理

文章来源声明: 原文作者:前端小小栈; 来源站点:掘金; 原文链接:https://juejin.cn/post/7687855997509287979; 本文基于上述来源整理/加工,觅优补充点评,仅供技术学习交流。版权归原作者所有。
觅优短评

文章用通俗类比和清晰结构,帮助 Java 初学者快速建立 Maven 全局认知;适合刚接触后端开发、需要理解依赖管理与项目构建标准流程的读者阅读。

如果你刚开始接触 Java 后端开发,经常会看到:
mvn clean
mvn install
mvn package
mvn <span>test</span>

项目里还经常有一个:

pom.xml

很多初学者的第一反应是:

Maven 不就是一个 Java 的包管理工具吗?

其实不完全是。

Maven 更准确地说,是一个 Java 项目的构建与项目管理工具。

它主要帮助我们解决:

  • 项目怎么编译
  • 测试怎么运行
  • 依赖怎么管理
  • 项目怎么打包
  • 多模块项目怎么组织
  • 构建过程怎么标准化

Apache Maven 官方也将它定位为用于 Java 项目构建和管理的工具,并通过 POM 和插件定义项目的构建过程。(Apache Maven)


一、没有 Maven 的时候,我们需要做什么?

假设我们有一个 Java 项目:

<span>src</span>/
 └── <span>Main</span><span>.java</span>

我们想运行它,大概需要经历:

Java 源代码
    ↓
javac 编译
    ↓
.<span>class</span> 文件
    ↓
运行

但真实项目很快就复杂起来了。

比如我们的项目需要:

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 全称:

Project <span>Object</span> Model

也就是:

项目对象模型。

它通常就是项目根目录下的:

pom.xml

例如:

<span><<span>project</span>></span>

    <span><<span>groupId</span>></span>com.example<span></<span>groupId</span>></span>

    <span><<span>artifactId</span>></span>demo<span></<span>artifactId</span>></span>

    <span><<span>version</span>></span>1.0.0<span></<span>version</span>></span>

    <span><<span>dependencies</span>></span>

        <span><<span>dependency</span>></span>
            <span><<span>groupId</span>></span>org.springframework.boot<span></<span>groupId</span>></span>
            <span><<span>artifactId</span>></span>spring-boot-starter-web<span></<span>artifactId</span>></span>
            <span><<span>version</span>></span>3.5.0<span></<span>version</span>></span>
        <span></<span>dependency</span>></span>

    <span></<span>dependencies</span>></span>

<span></<span>project</span>></span>

你可以把 pom.xml 理解成:

这个 Java 项目的身份证 + 配置文件。

它里面可以描述:

项目叫什么
项目版本是多少
使用什么 Java 版本
依赖哪些第三方库
使用哪些插件
怎么打包
父项目是谁
有哪些子模块

所以看到一个 Maven 项目,第一件事通常就是:

打开 pom.xml


四、dependency 是 Maven 最常见的配置

例如:

<span><<span>dependency</span>></span>
    <span><<span>groupId</span>></span>org.springframework.boot<span></<span>groupId</span>></span>
    <span><<span>artifactId</span>></span>spring-boot-starter-web<span></<span>artifactId</span>></span>
    <span><<span>version</span>></span>3.5.0<span></<span>version</span>></span>
<span></<span>dependency</span>></span>

它表示:

我的项目需要 spring-boot-starter-web 这个依赖。

这里有三个特别重要的字段。

groupId

表示组织或者项目所属的组织:

<span><<span>groupId</span>></span>org.springframework.boot<span></<span>groupId</span>></span>

可以理解成:

哪个公司 / 哪个组织


artifactId

表示具体的项目或者组件:

<span><<span>artifactId</span>></span>spring-boot-starter-web<span></<span>artifactId</span>></span>

可以理解成:

具体使用哪个库


version

表示版本:

<span><<span>version</span>></span>3.5.0<span></<span>version</span>></span>

也就是:

使用哪个版本

所以:

groupId
<span>+</span>
artifactId
<span>+</span>
version

基本可以唯一定位一个 Maven 依赖。


五、Maven 为什么能够自动下载 Jar?

这就涉及:

Repository(仓库)

Maven 世界里最重要的仓库之一是:

Maven Central

你在 pom.xml 中写:

<span><<span>dependency</span>></span>
    <span><<span>groupId</span>></span>xxx<span></<span>groupId</span>></span>
    <span><<span>artifactId</span>></span>xxx<span></<span>artifactId</span>></span>
    <span><<span>version</span>></span>xxx<span></<span>version</span>></span>
<span></<span>dependency</span>></span>

Maven 就会根据这些信息寻找对应的依赖。

大致过程:

pom.xml
   ↓
Maven
   ↓
查找依赖
   ↓
远程仓库
   ↓
下载 Jar
   ↓
本地仓库
   ↓
项目使用


六、什么是本地仓库?

第一次使用某个依赖时,Maven 通常会从远程仓库下载。

下载之后,会缓存到本地。

例如 Windows 用户通常可以在:

<span>C:\Users\用户名.m2\repository</span>

看到 Maven 的本地仓库。

里面可能有:

.m2
└── repository
<span>    └── org
        └── springframework
            └── ...
</span>

所以第二次构建项目时,如果本地已经存在对应版本:

Maven
 ↓
本地仓库有
 ↓
直接使用

就不需要每次重新下载。


七、Maven 最厉害的地方:传递依赖

假设你的项目依赖:

<span>A</span>

但是 A 又依赖:

<span>B</span>

B 又依赖:

C

传统方式可能需要你自己一个一个下载:

<span>A</span>
<span>B</span>
C

而 Maven 可以自动处理:

你的项目
   ↓
<span>A</span>
   ↓
<span>B</span>
   ↓
C

这就是:

传递依赖(Transitive Dependencies)。

所以你只需要声明自己直接需要的依赖,Maven 会根据依赖关系继续解析。

这也是 Maven 依赖管理非常重要的能力之一。(Apache Maven)


八、Maven 的标准项目结构

Maven 最大的特点之一,就是:

约定优于配置。

一个标准 Maven 项目通常是:

demo
├── pom<span>.xml</span>
└── <span>src</span>
    ├── <span>main</span>
    │   ├── java
    │   └── resources
    │
    └── test
        ├── java
        └── resources

其中:

<span>src</span>/<span>main</span>/java

放业务代码。

<span>src</span>/<span>main</span>/resources

放配置文件、资源文件。

src/test/java

放测试代码。

官方 Maven Getting Started Guide 也采用这一标准目录结构。(Apache Maven)

这样做有什么好处?

当你进入一个陌生的 Maven 项目时,不需要重新学习它的目录结构。

看到:

<span>src</span>/<span>main</span>/java

基本就知道:

Java 源代码在这里。

这就是 Maven 的:

约定优于配置。


九、Maven Lifecycle 是什么?

这是 Maven 初学者最容易混淆的地方。

经常看到:

mvn clean
mvn compile
mvn <span>test</span>
mvn package
mvn install

这些到底是什么?

可以先简单理解成:

Maven 定义了一套标准的项目构建生命周期。

例如:

validate
   ↓
compile
   ↓
<span>test</span>
   ↓
package
   ↓
verify
   ↓
install
   ↓
deploy

它们代表不同阶段。


十、几个最常用的 Maven 命令

1. clean

mvn clean

主要用于清理之前的构建结果。

例如:

target/

通常会被删除。

可以理解成:

把之前编译产生的东西清理掉。


2. compile

mvn <span>compile</span>

编译项目代码。

大概就是:

.java
 ↓
.<span>class</span>


3. test

mvn <span>test</span>

编译并运行测试。


4. package

mvn <span>package</span>

将项目打包。

例如:

target/demo-1.0.0.jar

或者 Web 项目可能生成:

xxx.war


5. install

mvn install

它不仅会构建项目,还会把生成的构件安装到本地 Maven 仓库。

可以理解成:

项目
 ↓
编译
 ↓
测试
 ↓
打包
 ↓
安装到 ~/.m2/repository

这样其他本地 Maven 项目就可以引用它。


十一、为什么执行 package 会自动编译和测试?

比如你执行:

mvn <span>package</span>

你可能会发现:

compile
<span>test</span>
package

都执行了。

为什么?

因为 Maven 的生命周期阶段是有顺序的。

你执行:

mvn <span>package</span>

相当于告诉 Maven:

把项目构建到 package 阶段。

那么 package 前面的必要阶段也会执行。

所以:

mvn <span>package</span>

通常不需要你再手动执行:

mvn compile
mvn <span>test</span>


十二、Plugin 又是什么?

Maven 本身并不是把所有事情都硬编码进去。

它大量依赖:

Plugin(插件)。

例如:

编译
测试
打包
生成文档
代码检查
发布

很多能力都是通过插件完成的。

可以简单理解:

Maven
  ↓
生命周期
  ↓
插件
  ↓
具体执行任务

例如编译 Java:

Maven Compiler Plugin

执行测试:

Maven Surefire Plugin

所以 Maven 可以理解成一个:

围绕生命周期、插件和项目模型组织起来的构建系统。


十三、Maven 和 npm 有什么区别?

如果你做过前端,这个对理解 Maven 非常有帮助。

前端:

<span>package</span>.json
      ↓
npm install
      ↓
node_modules

Java:

pom.xml
      ↓
mvn package
      ↓
~/.m2/repository

可以粗略类比:

前端Java
package.jsonpom.xml
npmMaven
npm installMaven 下载依赖
node\_modulesMaven 本地仓库
packageJar
npm scriptsMaven Plugin / Lifecycle

当然,这只是帮助理解的类比,两者的构建模型并不完全相同。


十四、Maven 到底解决了什么问题?

如果把 Maven 浓缩成一句话:

Maven 把 Java 项目的构建、依赖、测试、打包和发布流程标准化了。

以前可能是:

开发人员 <span>A</span>
自己写构建脚本

开发人员 <span>B</span>
自己管理 Jar

开发人员 C
自己设计项目结构

最后每个项目都不一样。

Maven 希望做到:

统一项目结构
<span>        ↓
统一依赖管理
        ↓
统一构建流程
        ↓
统一测试流程
        ↓
统一打包方式
</span>

所以当你进入一个新的 Java Maven 项目时,通常只需要先看:

pom.xml

然后执行:

mvn clean <span>package</span>

就能快速理解和构建项目。


十五、初学 Maven,真正需要掌握什么?

不要一开始就研究 Maven 几百个配置项。

入门阶段先掌握这几个:

① pom.xml

② groupId / artifactId / version

③ dependency

④ Repository

⑤ 本地仓库 ~/.m2

⑥ Maven 生命周期

⑦ clean / compile / <span>test</span> / package / install

⑧ Plugin

⑨ 传递依赖

⑩ Maven 标准项目结构

把这几个概念搞懂,已经足够应付绝大多数日常 Maven 操作。


十六、最后用一张图理解 Maven

可以把 Maven 想象成:

<span>                    Maven
                      │
          ┌───────────┼───────────┐
          ↓           ↓           ↓
        POM       Lifecycle    Repository
          │           │           │
          ↓           ↓           ↓
       依赖配置     构建流程      下载依赖
          │           │           │
          └───────────┼───────────┘
                      ↓
                  Plugin
                      ↓
              编译 / 测试 / 打包
                      ↓
                  Jar / War
</span>

所以 Maven 并不只是:

“Java 的依赖管理工具。”

更准确的理解是:

Maven 是一个以 POM 为核心,通过依赖管理、生命周期和插件来标准化 Java 项目构建与管理的工具。