Maven 定义了三个类别的生命周期:
Maven 的每个生命周期内部,又细分成多个执行阶段
每个生命周期间是独立的,但是同一生命周期内的阶段是有顺序的,当一个阶段执行时,在它前面的所有同一生命周期的阶段都会被执行,比如我们执行 mvn post-clean
那么 pre-clean
和 clean
两个阶段也会被自动执行
Maven 只是定义了这些执行阶段,并没有对其具体实现,所有的实现都是由插件来提供,Maven 只是起到了调用作用,和一点点的规范作用,为啥说只是一点点呢,比如 Maven 定义 clean 阶段的本意是想让插件实现时做清理操作,但是插件实现时偏偏在 clean 阶段做了打包处理,那也没有办法
Clean 生命周期内部阶段,按阶段顺序列举
阶段名称 | Maven 建议插件实现该阶段时的处理 |
---|---|
pre-clean | 清理前的处理 |
clean | 真正的清理处理 |
post-clean | 清理后的处理 |
Default 生命周期内部阶段,只列举核心阶段,按阶段顺序列举
阶段名称 | Maven 建议插件实现该阶段时的处理 |
---|---|
validate | 校验项目的正确性 |
compile | 编译项目中 src=>main 和 src=>test 目录下的源代码 |
test-compile | 编译项目中 src=>test 目录下的源代码 |
test | 执行 test-compile 编译后的二进制文件 |
package | 生成目标包,jar war 等 |
install | 将生成的包安装到本地仓库 |
deploy | 将生成的包安装到远程仓库 |
Site 生命周期内部阶段,按阶段顺序列举
阶段名称 | Maven 建议插件实现该阶段时的处理 |
---|---|
pre-site | 生成站点文档前的处理 |
site | 真正生成站点文档的处理 |
post-site | 生成站点文档后的处理 |
site-deploy | 将站点文档部署到服务器的处理 |
执行 Maven 生命周期的命令
执行 Maven 生命周期的命令格式是:mvn 阶段名
,比如:mvn clean
,就会执行与 clean 阶段
绑定的插件功能(同一阶段可以绑定多个插件,运行时都会被执行),注意:生命周期命令必须在有 pom.xml
的路径下运行
先看一下执行插件的命令 mvn 插件名:目标名
插件名和目标名
插件名:
插件名与我们自定义插件工程的
息息相关,所以
不能乱起,需要满足规则:
必须满足上面两个规则中的一个,而 ${name} 部分就会自动变成我们的插件名,
比如 artifactId 是 ares5k-maven-plugin
,那么我们的插件名就是 ares5k
目标名:
每个自定义插件中,可以定义多个功能,每个功能需要用目标名来标识,后面用命令调用插件的时候,需要指定目标名来明确具体调用插件中的哪一个功能,大概原理如下图:
自定义插件示例
在一个
符合规范的 Maven 工程的基础上,实现自定义 Maven 插件,大概需要五个步骤:
1. 设置打包类型
在 pom.xml
中设置当前 Maven 工程的打包类型
<packaging>maven-pluginpackaging>
2. 引入依赖
在 pom.xml
中引入两个必要依赖
<dependencies>
<dependency>
<groupId>org.apache.mavengroupId>
<artifactId>maven-plugin-apiartifactId>
<version>3.5.4version>
dependency>
<dependency>
<groupId>org.apache.maven.plugin-toolsgroupId>
<artifactId>maven-plugin-annotationsartifactId>
<version>3.5.2version>
dependency>
dependencies>
3. 实现功能
新建 Java 类,并继承 AbstractMojo
抽象类来实现自定义插件的功能,然后通过 @Mojo
注解给功能绑定一个目标名,后面要通过目标名来调用该功能(如果插件有多个功能,那么就创建多个 Java 类,并分别设置目标名)
package com.ares5k;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugins.annotations.Mojo;
/**
* 自定义插件功能
*
* @author ares5k
*/
@Mojo(name = "print") // 绑定该功能的目标名
public class Hello extends AbstractMojo {
/**
* 实现自定义插件功能
*/
@Override
public void execute() {
System.out.println("ares5k's plugin is running!");
}
}
5. 部署插件
插件功能写好后,要将插件安装和注册
(1)安装插件,使用 Maven 生命周期命令 mvn install
将工程安装到本地仓库或使用生命周期命令 mvn deploy
将项目部署到远程仓库,二者都可以,视情况而定,生命周期命令需要在有 pom.xml
的路径下运行
(2)在 Maven 安装目录/conf/settings.xml
中,添加下面代码注册插件:
<pluginGroups>
<pluginGroup>com.ares5kpluginGroup>
pluginGroups>
这个地方使用了 Maven 生命周期构建命令 mvn install
或 mvn deploy
,我们并没有对 install
和 deploy
阶段绑定插件,至于为何这两个阶段可以执行,是因为 Maven 对一些核心阶段绑定了默认插件,这个在下一部分会有说明
这个时候我们的自定义插件就可以使用了, 我们可以通过执行插件的命令实验一下,示例中的插件名是 ares5k
,定义了一个功能,其目标名是 print
,所以执行插件的命令为 mvn ares5k:print
5. 绑定生命周期
上一步,我们已经可以执行自定义插件了,但是我们使用的是执行插件的命令 mvn 插件名:目标名
,实际使用时,一般习惯将插件和 Maven 的生命周期进行绑定,这样使用生命周期命令 mvn 阶段名
就可以执行插件了,语法更方便一些
想让自定义插件中的目标 print
绑定到 Maven 生命周期的 clean
阶段,就可以在 pom.xml
中添加下面代码:
<build>
<plugins>
<plugin>
<groupId>com.ares5kgroupId>
<artifactId>ares5k-maven-pluginartifactId>
<version>1.0-SNAPSHOTversion>
<executions>
<execution>
<phase>cleanphase>
<goals>
<goal>printgoal>
goals>
execution>
executions>
plugin>
plugins>
build>
使用生命周期命令 mvn clean
测试插件中目标名为 print
的功能是否成功绑定到生命周期的 clean
阶段
在前面已经发现了 clean
、install
、deploy
这三个阶段,虽然我们并没有对其绑定插件,但是也能够正确执行,这是因为 Maven 对一些比较核心的生命周期阶段进行了默认的插件绑定,几个常用的如下:
插件名 | 目标名 | 阶段名 | 目标功能 |
---|---|---|---|
maven-clean-plugin | clean | clean | 删除原构建目录 target |
maven-resources-plugin | resources | resources | 将 main/resources 中的文件复制到 target 里 |
maven-compiler-plugin | compile | compile | 编译 main/java 中的 Java 文件,并将结果放到 target 里 |
maven-surefire-plugin | test | test | 执行 test/java 中的测试代码,一般搭配 junit |
maven-jar-plugin | jar | package | 将项目打成 jar 包 |
maven-install-plugin | install | install | 将打包后的项目安装到本地仓库 |
maven-deploy-plugin | deploy | deploy | 将打包后的项目发送到到远程仓库 |