Maven介绍
Maven 翻译为”专家”、”内行”,是 Apache 下的一个纯 Java 开发的开源项目。基于项目对象模型(缩写:POM)概念,Maven利用一个中央信息片断能管理一个项目的构建、报告和文档等步骤。
Maven 是一个项目管理工具,可以对 Java 项目进行构建、依赖管理。
Maven 也可被用于构建和管理各种项目,例如 C#,Ruby,Scala 和其他语言编写的项目。Maven 曾是 Jakarta 项目的子项目,现为由 Apache 软件基金会主持的独立 Apache 项目。
Maven POM
POM( Project Object Model,项目对象模型 ) 是 Maven 工程的基本工作单元,是一个XML文件,包含了项目的基本信息,用于描述项目如何构建,声明项目依赖,等等。
执行任务或目标时,Maven 会在当前目录中查找 POM。它读取 POM,获取所需的配置信息,然后执行目标。
POM 中可以指定以下配置:
项目依赖
插件
执行目标
项目构建 profile
项目版本
项目开发者列表
相关邮件列表信息
所有 POM 文件都需要 project 元素和三个必需字段:groupId,artifactId,version。
| 节点 | 描述 |
|---|---|
| modelVersion | 模型版本 |
| groupId | 这是工程组的标识。它在一个组织或者项目中通常是唯一的 |
| artifactId | 这是工程的标识。它通常是工程的名称 |
| version | 这是工程的版本号。在 artifact 的仓库中,它用来区分不同的版本 |
父(Super)POM
在 Java 中,所有的类都继承自 Object 超类,而在 maven 中也存在 The Super POM,所有 maven 工程的pom 文件都继承自该文件,那这个 The Super POM 中设置了什么呢?
下面展示的 maven 3.5.4 版本的 The Super POM。
1 | <project> |
我对上面的 pom 文件进行了删减,仅展示了部分内容,它们可以概括为以下 3 个部分:
- 默认的 repository
maven 默认使用官方提供的 central repository,这也是你可以开箱即用的原因,而在安装阶段配置国内的镜像源就是为了替换默认的设置。
- 标准的目录骨架
在 build 标签中,可以看到如 sourceDirectory 、 testSourceDirectory 、 outputDirectory 等标签,这些标签为我们设置了默认的 maven 目录骨架,明确了源代码目录、测试目录、输出目录等各种目录,使得我们在接触一个任何一个 maven 工程时都可以快速找到相对应的代码入口。
这也提示我们,其实我们可以自定义 maven 目录结构,但完全不推荐这么做。
- 默认的插件版本
在 The Super POM 中还定义了多个默认插件的版本,使得你省去了配置插件的工作,当然你也可以自己设置插件的版本号。
Maven 使用 effective pom(Super pom 加上工程自己的配置)来执行相关的目标,它帮助开发者在 pom.xml 中做尽可能少的配置,当然这些配置可以被重写。
使用以下命令来查看 Super POM 默认配置:
1 | mvn help:effective-pom |
Effective POM 的结果是经过继承、插值之后,使配置生效。
常用POM标签解析
1 |
|
Maven生命周期
Maven 构建生命周期定义了一个项目构建跟发布的过程。
一个典型的 Maven 构建(build)生命周期是由以下几个阶段的序列组成的:

| 阶段 | 处理 | 描述 |
|---|---|---|
| validate | 验证项目 | 验证项目是否正确且所有必须信息是可用的 |
| compile | 执行编译 | 源代码编译在此阶段完成 |
| test | 测试 | 使用适当的单元测试框架(例如JUnit)运行测试。 |
| package | 打包 | 创建JAR/WAR包如在 pom.xml 中定义提及的包 |
| verify | 检查 | 对集成测试的结果进行检查,以保证质量达标 |
| install | 安装 | 安装打包的项目到本地仓库,以供其他项目使用 |
| deploy | 部署 | 拷贝最终的工程包到远程仓库中,以共享给其他开发人员和工程 |
maven 定义了三种构建**生命周期(Build Lifecycle),分别是 **clean、default、site,它们分别用于不同的任务:
- clean 生命周期:处理工程构建前的清理工作;
- default 生命周期:处理工程的编译、打包、部署;
- site 生命周期:生成工程的文档。
每一种构建生命周期都由多个构建阶段(Build Phase)组成,如 clean 生命周期就由 pre-clean、clean、post-clean 三个构建阶段组成,而 default 声明周期则有 23 个构建阶段,详细内容可查看官方文档。
maven 插件
虽然 maven 定义了构建生命周期和构建阶段,并指明了每个阶段的任务目标,但这些目标都是由 maven 插件(plugin)实现的,可以将构建阶段类比为一个 Java 接口,而将插件类比为一个 Java 实现类。
maven 插件有一个很重要的概念:goal,你可以直译为“目标”,但整个知识库仍直接使用英语原文。一个插件可以有多个 goal,一个 goal 对应一个功能,比如 maven-compiler-plugin 插件,就有两个 goal: compile 和 testCompile ,前者表示编译工程代码,后者表示编译工程测试代码。
内置生命周期绑定
“生命周期绑定”指的是将“生命周期的构建阶段”与“plugin:goal”绑定,而“内置(build-in)”指的是这是 maven 默认的。需要特别指出的是:不是所有构建阶段都(默认)绑定了 plugin:goal。
下面列出了几个常见的生命周期绑定,详细内容请查阅官方文档:

构建阶段的有序性
使用 mvn compile 命令编译代码时的输出:
1 | $ mvn compile |
首先, mvn compile 命令表示执行(default 生命周期的)compile 阶段,而 compile 阶段默认绑定了 maven-compiler-plugin:compile ,所以 mvn compile 命令就相当于执行 mvn compiler:compile 命令,因此在第 12 行你看到了对应的提示。
那为什么在执行 maven-compiler-plugin:compile 前会先执行 maven-resources-plugin:resources 呢?这就与“构建阶段的有序性”有关了。
“构建阶段的有序性”是指在同一种生命周期内,不同构建阶段的执行是有序的,执行某个阶段前,必须先执行完该阶段的所有前置阶段。如 compile 阶段属于 default 生命周期,而 process-resources 阶段在 compile 阶段之前,且默认绑定了 maven-resources-plugin:resources ,所以你看到第 8 行的提示。
前面说过,maven 并未对所有阶段都绑定 plugin:goal,所以即使构建阶段有序,有些阶段也可能并未真正执行。
至此,构建第一个 maven 工程时留下的疑惑就只剩下第 9 行和第 14 行的警告了,这个问题将在后文进行解答。