前言

Github:https://github.com/HealerJean

博客:http://blog.healerjean.com

1、Maven 构建(build)生命周期的几个阶段

一个典型的 Maven 构建(build)生命周期是由以下几个阶段的序列组成的:

image-20210806152255509

阶段 处理 描述
验证 validate 验证项目 验证项目是否正确且所有必须信息是可用的
编译 compile 执行编译 源代码编译在此阶段完成
测试 Test 测试 使用适当的单元测试框架(例如JUnit)运行测试。
包装 package 打包 创建JAR/WAR包如在 pom.xml 中定义提及的包
检查 verify 检查 对集成测试的结果进行检查,以保证质量达标
安装 install 安装 安装打包的项目到本地仓库,以供其他项目使用
部署 deploy 部署 拷贝最终的工程包到远程仓库中,以共享给其他开发人员和工程

2、Maven 有以下三个标准的生命周期

为了完成 default 生命周期,这些阶段(包括其他未在上面罗列的生命周期阶段)将被按顺序地执行。

Maven 有以下三个标准的生命周期:

clean:项目清理的处理

default build):项目构建+部署的处理

site:项目站点文档创建的处理

2.1、Clean 生命周期

当我们执行 mvn post-clean 命令时,Maven 调用 clean 生命周期,它包含以下阶段:

pre-clean:执行一些需要在clean之前完成的工作

clean:移除所有上一次构建生成的文件

post-clean:执行一些需要在clean之后立刻完成的工作

2.1.1、mvn clean

mvn clean 中的 clean 就是上面的 clean,在一个生命周期中,运行某个阶段的时候,它之前的所有阶段都会被运行,也就是说,如果执行 mvn clean 将运行以下两个生命周期阶段:

pre-clean, clean

2.1.2、mvn post-clean

如果我们运行 mvn post-clean ,则运行以下三个生命周期阶段:

pre-clean, clean, post-clean

2.2、Default (Build) 生命周期

这是 Maven 的主要生命周期,被用于构建应用,包括下面的 23 个阶段:

validate(校验) 校验项目是否正确并且所有必要的信息可以完成项目的构建过程。
initialize(初始化) 初始化构建状态,比如设置属性值。
generate-sources(生成源代码) 生成包含在编译阶段中的任何源代码。
process-sources(处理源代码) 处理源代码,比如说,过滤任意值。
generate-resources(生成资源文件) 生成将会包含在项目包中的资源文件。
process-resources (处理资源文件) 复制和处理资源到目标目录,为打包阶段最好准备。
compile(编译) 编译项目的源代码。
process-classes(处理类文件) 处理编译生成的文件,比如说对Java class文件做字节码改善优化。
generate-test-sources(生成测试源代码) 生成包含在编译阶段中的任何测试源代码。
process-test-sources(处理测试源代码) 处理测试源代码,比如说,过滤任意值。
generate-test-resources(生成测试资源文件) 为测试创建资源文件。
process-test-resources(处理测试资源文件) 复制和处理测试资源到目标目录。
test-compile(编译测试源码) 编译测试源代码到测试目标目录.
process-test-classes(处理测试类文件) 处理测试源码编译生成的文件。
test(测试) 使用合适的单元测试框架运行测试(Juint是其中之一)。
prepare-package(准备打包) 在实际打包之前,执行任何的必要的操作为打包做准备。
package(打包) 将编译后的代码打包成可分发格式的文件,比如JAR、WAR或者EAR文件。
pre-integration-test(集成测试前) 在执行集成测试前进行必要的动作。比如说,搭建需要的环境。
integration-test(集成测试) 处理和部署项目到可以运行集成测试环境中。
post-integration-test(集成测试后) 在执行集成测试完成后进行必要的动作。比如说,清理集成测试环境。
verify (验证) 运行任意的检查来验证项目包有效且达到质量标准。
install(安装) 安装项目包到本地仓库,这样项目包可以用作其他本地项目的依赖。
deploy(部署) 将最终的项目包复制到远程仓库中与其他开发者和项目共享。

2.2.1、mvn compile

只有该阶段之前以及包括该阶段在内的所有阶段会被执行。

2.2.2、mvn install

这个命令在执行 install 阶段前,按顺序执行了 default 生命周期的阶段 (validate,compile,package,等等),我们只需要调用最后一个阶段,如这里是 install

mvn install

2.2.3、mvn clean deploy

在构建环境中,使用下面的调用来纯净地构建和部署项目到共享仓库中

这行命令也可以用于多模块的情况下,即包含多个子项目的项目,Maven 会在每一个子项目执行 clean 命令,然后再执行 deploy 命令。

mvn clean deploy

2.3、Site 生命周期

Maven Site 插件一般用来创建新的报告文档、部署站点等。 使用mavensite 插件生成项目相关信息的网站并且可以在浏览器中查看项目的站点,以下的文章是最基本的操作,可以添加其他的属性生成更加完善的站点文档。

pre-site:执行一些需要在生成站点文档之前完成的工作

site生成项目的站点文档

post-site: 执行一些需要在生成站点文档之后完成的工作,并且为部署做准备

site-deploy:将生成的站点文档部署到特定的服务器上

这里经常用到的是site 阶段和 site-deploy阶段,用以生成和发布Maven站点,这可是Maven相当强大的功能,Manager比较喜欢,文档及统计数据自动生成,很好看。 在下面的例子中,我们将 maven-antrun-plugin:run 目标添加到 Site 生命周期的所有阶段中。这样我们可以显示生命周期的所有文本信息。

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-site-plugin</artifactId>
  <version>3.3</version>
  <configuration>
    <locales>zh_CN</locales>
  </configuration>
</plugin>

image-20210806165622723

3、scope

Maven 的生命周期存在编译、测试、运行这些过程,那么显然有些依赖只用于测试,

⬤ 比如junit;有些依赖编译用不到,只有运行的时候才能用到

⬤ 比如 mysql 的驱动包在编译期就用不到(编译期用的是JDBC接口),而是在运行时用到的;

⬤ 还有些依赖,编译期要用到,而运行期不需要提供,因为有些容器已经提供了,比如servlet-api在tomcat中已经提供了,我们只需要的是编译期提供而已。

总结说来,在POM 4中,<dependency>中还引入了<scope>,它主要管理依赖的部署。大致有compileprovidedruntimetestsystem等几个。

3.1、compile (编译范围)

默认就是 compile该依赖需要参与当前项目的编译、测试、运行、打包

3.2、runntime (运行时范围)

runntime 表示被依赖项目无需参与项目的编译,不过后期的测试和运行周期需要其参与。与compile相比,跳过编译而已.

比如,你可能在编译的时候只需要JDBC API JAR,而只有在运行的时候才需要JDBC驱动实现。

3.3、 test (测试范围)

test 范围依赖 在一般的编译和运行时都不需要,它们只有在测试编译和测试运行阶段可用。比如

<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-test</artifactId>
    <scope>test</scope>
</dependency>

3.4、provided (已提供范围)

provided 表明该依赖已经提供,故只在未提供时才被使用,

应用场景是你定义了一个 Servlet,此刻得需要Servlet-api.jar 才能编译成功,但是当你达成war 包时,你并不想将 Servlet-api.jar 包进去,因为Tomcat等容器会提供

该依赖会由系统组件提供,不需手动添加,只存在编译、运行、测试阶段,打包是不用包进去,打包阶段做了 exclude动作provided 意味着打包的时候可以不用包进去,别的设施(Web Container)会提供

3.5、system (系统范围)

被依赖项不会从 maven 仓库下载,而是从本地系统指定路径下寻找,需要 systemPath 属性

system 范围依赖与 provided 类似,但是你必须显式的提供一个对于本地系统中JAR 文件的路径,这么做是为了允许基于本地对象编译,而这些对象是系统类库的一部分。这样的构件应该是一直可用的,Maven 也不会在仓库中去寻找它

从参与度来说,与provided相同,不过被依赖项不会从maven仓库抓,而是从本地文件系统拿,一定需要配合systemPath属性使用

ContactAuthor