引言
承接上一篇《Maven学习(二)————Maven核心概念(一)》,介绍 Maven 生命周期、插件、目标、继承、聚合等一些概念。
一、Maven 生命周期
1.1 理解 Maven 生命周期及主要构建过程
Maven 构建生命周期,也称Maven 项目的生命周期,或 Maven 生命周期。
它描述了一个项目从编译到发布的整个过程。一个典型的 Maven 工程构建(build)生命周期是由以下几个主要阶段(phase)组成的。
阶段 | 处理 | 描述 |
---|---|---|
验证 validate | 验证项目 | 验证项目是否正确且所有必须信息是可用的 |
编译 compile | 执行编译 | 源代码编译在此阶段完成 |
测试 Test | 测试 | 使用适当的单元测试框架(例如JUnit)运行测试。 |
包装 package | 打包 | 创建JAR/WAR包如在 pom.xml 中定义提及的包 |
检查 verify | 检查 | 对集成测试的结果进行检查,以保证质量达标 |
安装 install | 安装 | 安装打包的项目到本地仓库,以供其他项目使用 |
部署 deploy | 部署 | 拷贝最终的工程包到远程仓库中,以共享给其他开发人员和工程 |
Maven 有三个标准生命周期:clean、 build(或default)、site(生成站点,适用于动态 web 项目)。
理解构建阶段和生命周期的关系很重要,一个生命周期可以划分为多个构建阶段,Maven 的三个标准生命周期包括以下这些构建阶段:
【注意】build 生命周期中总共包含 23 个构建阶段,但比较重要的构建阶段就是上图这些,它们并非如图所示是紧挨着执行的,但可以保证顺序一定会如上图所示。当我们执行 install 构建过程的时候,maven会自动从 pre-clean 阶段执行,一直到 install。
1.2 构建阶段与 Maven 命令
Maven 的三个标准生命周期以及构建阶段,都会有特定的maven 指令,如上面所述,比较重要的构建阶段包括:compile、test、install等,它们对应的命令包含但不限于以下这些:
1、mvn clean:清理上次编译生成的 class 文件
2、mvn compile:编译主程序(main 目录下的源码文件)
3、mvn test-compile:编译测试程序(test 目录下的源码文件)
4、mvn test : 执行测试
5、mvn package:获取编译后的字节码文件,并按照可发布的格式打包成 jar 或 war
6、mvn install:安装工程包到本地仓库,该 jar 包可以作为本地其他工程的依赖。
7、mvn site:生成站点(此项构建过程包含在 site 生命周期中,上图未列出,只针对于动态 web 项目)
如果手动执行这些命令,需要在 pom.xml 文件所在的目录下打开 cmd 才可以,否则会构建失败。通常情况下,我们会使用开发工具中的 maven 插件来执行这些命令,而不是手动键入这些 maven 命令。
(目前很多项目都是 spring boot 项目,多为jar 包部署,所以本文暂不涉及 动态 web 工程相关的详细描述)
二、Maven 插件及执行目标
2.1 插件 plugin
Maven 插件用于完成 maven 项目的实际构建工作。
上文中提到, Maven 包括三个标准生命周期,这三个标准生命周期以 build 作为重要,它们包含了许多细分的构建阶段,这些阶段我们可以理解为一个概念性的接口,规定了这个阶段所要完成的工作,而由 Maven 插件来实际真正完成这些工作内容。
比如,我们输入 mvn clean 来完成 clean 阶段的旧字节码文件的清理工作,但 clean 的具体操作是由 maven-clean-plugin 插件来完成的。所以说, Maven 生命周期的每一个阶段的具体实现都是由 Maven 插件来完成的,Maven 实际上是一个依赖插件执行的框架。
常用的插件有如下这些:
插件 | 描述 |
---|---|
clean | 构建之后清理目标文件。删除目标目录。 |
compiler | 编译 Java 源文件。 |
surefile | 运行 JUnit 单元测试。创建测试报告。 |
jar | 从当前工程中构建 JAR 文件。 |
war | 从当前工程中构建 WAR 文件。 |
javadoc | 为工程生成 Javadoc。 |
antrun | 从构建过程的任意一个阶段中运行一个 ant 任务的集合。 |
2.2 目标 goal
maven 中 目标的概念与插件紧密联系。一个插件目标可以代表一个特定的任务,它是比构建阶段更精细的划分。
这些目标被绑定在各自所属的不同阶段,或者无绑定,无绑定的目标可以穿插在构建过程之间独立执行。
插件通常提供了一个目标的集合,并且可以使用下面的语法执行:
mvn [plugin-name]:[goal-name]
例如,我们可以单独执行 compiler插件中的 compile 目标(任务):
mvn compiler:compile
三、Maven继承
Maven 提供一种依赖继承的方式,用于解决一些公共依赖统一版本的问题。
比如,三个maven 工程都依赖了 JUnit ,但是可能三个项目都引入了不同的版本依赖,这可能会造成某些情况下的测试结果出错的问题。
这个时候,我们就可以将JUnit 依赖提升到父工程中,统一指定版本号。在这种情况下,子工程只需要在依赖中标明 GAV 依赖坐标的前两项即可。这样,就可以在父工程中统一管理版本号,便于管理。
3.1 操作步骤
由于本文是概念性描述,后面会有实操的演示,这里还需要留意记忆。
1、创建一个Maven工程作为父工程。打包方式是pom
2、在子工程中通过<parent>标签声明父工程的引用
3、将子工程的坐标中与父工程坐标重复的部分剔除,主要是groupId 和 version
4、在父工程中统一junit的依赖
5、在子工程中删除junit依赖的版本号部分
【注意】配置继承后,执行安装命令时要先安装父工程。
四、Maven聚合概念
到目前为止,我们已经知道,maven可以轻松的管理项目的构建。在第一篇Maven 学习中《Maven学习(一)————Maven技术概述》引言部分,我提到项目开发中,项目过大导致工程代码庞大而出现的分工困难问题。
那么我们可以将项目拆分成多个 业务子模块,这些模块都是 maven 项目,然后通过彼此依赖的方式,建立联系(注意,两个项目 A 和 B 不能相互依赖,彼此依赖的意思是多个 maven 项目存在依赖关系,而两个项目无法双向依赖)。
但这依然存在一个问题,即需要在构建的时候,分别去构建每一个 maven 子工程,有没有可以一键构建所有子工程的方法?
maven 聚合就是为了解决这个问题。
maven 聚合的概念本身和 maven 继承没有什么交集,但是为了简化操作,在实际开发过程中,人们往往更习惯于将 maven 的父工程作为一个总的聚合工程。
操作非常简单,只需要在 pom 文件中加入<modules>标签项即可,如下图所示:
这样,只需要在 parent 项目上进行 maven 操作即可。
在接下来的文章中,我会以 demo 的形式演示一些 maven 应用于工程项目上的一些习惯性规则。包括一些在核心概念中并没有介绍的内容,也会在下面的实践中逐一展开。不得不说,虽然maven 应用起来非常简单,但是要想真正弄懂,还是需要下一番功夫的。