Maven插件基础

Maven核心仅仅定义了抽象的生命周期具体任务交给插件来完成,插件以独立的构件形式存在,Maven核心分发包不到3M大小,Maven会在需要时下载并使用插件。如maven-dependency-plugin能分析项目依赖,找出潜在无用依赖,列出项目依赖树,分析依赖来源等

生命周期的阶段与插件的目标相互绑定,来完成某个具体的构建任务,例如项目编译任务对应了default生命周期的compile阶段,而maven-compiler-plugin插件的compile目标能完成该任务,将其绑定能实现项目编译目的

插件的每个目标都对应一个功能,如dependency:analyzedependency:treedependency:list冒号前面是插件前缀冒号后面是插件目标

插件绑定

Maven核心默认为一些主要的生命周期阶段内置绑定了很多插件目标,当调用生命周期阶段时,对应的插件目标就会执行相应的任务。

生命周期阶段 插件目标 执行任务
pre-clean - -
clean maven-clean-plugin:clean 删除项目输出目录
post-clean - -
pre-site - -
site maven-site-plugin:site 生成项目站点
post-site - -
site-deploy maven-site-plugin:deploy 将项目站点部署到远程服务器
pro-resources maven-resources-plugin:resources 复制主资源文件至主输出目录
compile maven-compiler-plugin:compile 编译主代码至主输出目录
process-test-resources maven-resources-plugin:testResources 复制测试资源文件至测试输出目录
test-compile maven-compiler-plugin:testCompile 编译测试代码至测试输出目录
test maven-surefire-plugin:test 执行测试用例
package maven-jar-plugin:jar 创建项目jar包
install maven-install-plugin:install 将项目输出构件安装到本地仓库
deploy maven-deploy-plugin:deploy 将项目输出构件部署到远程仓库

上表只列出了cleansite生命周期插件绑定关系,以及default生命周期拥有插件绑定关系的阶段,default生命周期还有很多其他阶段,默认没有绑定任何插件,故无任何实际行为

还可以自定义将某个插件目标绑定到生命周期的某个阶段上,可以通过phrase标签将goals标签中指定的插件目标绑定到具体的生命周期阶段上。

1
2
3
4
5
6
7
8
9
10
11
12
13
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>xml-maven-plugin</artifactId>
<executions>
<execution>
<id>xslt-generate</id>
<phase>compile</phase>
<goals>
<goal>transform</goal>
</goals>
</execution>
</executions>
</plugin>

executions下每一个execution都可以用来配置执行一个任务,通过phasexml-maven-plugintransform目标绑定到default生命周期的compile阶段上。goals用于配置指定要执行的插件目标

很多插件目标在编写时已定义了默认绑定阶段,即使不通过phase元素配置生命周期阶段,也能绑定到生命周期中去。

多个插件目标绑定到同一个生命周期阶段时,插件声明的先后顺序决定了目标执行的顺序

插件配置

完成插件目标和声明周期阶段绑定后,还能配置插件目标参数,几乎所有插件目标都有一些可配置的参数,可通过命令行POM配置等方式来配置。

Maven命令行中可以使用:-D参数键=参数值,来配置插件目标参数。例如:mvn install -Dmaven.test.skip=true

并非所有插件参数都适合命令行配置,可以在插件声明时,对插件进行全局配置,所有基于该插件的目标任务都会使用全局配置。还可以为插件的某个目标配置特定的参数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<plugin>
<groupId>org.jvnet.jaxb2.maven2</groupId>
<artifactId>maven-jaxb2-plugin</artifactId>
<!-- 全局配置 -->
<configuration>
<schemaDirectory>src/main/resources/xsd</schemaDirectory>
<generateDirectory>src/main/java/</generateDirectory>
</configuration>
<executions>
<execution>
<id>xsd1-generate</id>
<goals>
<goal>generate</goal>
</goals>
<!-- 特定目标任务配置 -->
<configuration>
<schemaIncludes>
<include>test.xsd</include>
</schemaIncludes>
</configuration>
</execution>
</executions>
</plugin>

获取插件信息

主要的插件都来自Apache和Codehaus,文档链接分别为 http://maven.apache.org/plugin/index.htmlhttp://mojo.codehaus.org/plugins.html,下载地址分别为 http://repo1.maven.org/maven2/org/apache/maven/pluginshttp://repository.codehaus.org/org/codehuas/mojo

可以使用maven-help-plugin查看插件详细信息。查看插件目标默认绑定阶段mvn help:目标-DgroupId:artifactId:version,例如:mvn help:describe-Dplugin = org.apache.maven.plugins:maven-source-plugin:2.1.1,可以省去版本信息,可以使用插件目标前缀替换坐标,加上goal参数仅查询描述插件目标信息,加上detail参数查询详细信息,例如:mvn help:describe-Dplugin=compiler[-Dgoal=compiler][-Ddetail]

明显可以发现命令行传入参数不同于该插件目标参数名称,命令行参数是由插件参数表达式(Expression)决定的,例如surefire:test skip参数表达式为${maven.test.skip}。并非所有插件目标都有表达式,一些插件目标参数只能在POM中配置。

插件解析机制

与依赖构件一样,插件构件同样基于坐标存储在Maven仓库中。需要时,Maven会从本地仓库寻找插件,若不存在,则从远程仓库查找,找到后下载到本地仓库使用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<pluginRepositories>
<pluginRepository>
<id>central</id>
<name>Central Repository</name>
<url>https://repo.maven.apache.org/maven2</url>
<layout>default</layout>
<snapshots>
<enabled>false</enabled>
</snapshots>
<releases>
<updatePolicy>never</updatePolicy>
</releases>
</pluginRepository>
</pluginRepositories>

所有子元素表达含义与依赖远程仓库配置完全一样。

若插件的groupIdorg.apache.maven.plugins表示为官方插件,在配置插件信息时可以省略groupId,不推荐使用。

插件版本的解析与依赖版本解析类似,未提供版本会自动解析版本,Maven在超级POM中为所有核心插件设定了版本,在使用核心插件时即使不做任何配置,其版本已经确定了。

若某个插件未设定版本,又不是核心插件,Maven会检查所有仓库中可用版本,然后做出选择,选择版本方式与依赖类似,都是到归并后的元数据文件中确定版本

插件解析元数据时,会默认使用org.apache.maven.pluginsorg.codehaus.mojo两个groupId,也可以通过settings配置让Maven检查其他groupId上的插件仓库元数据。

1
2
3
<pluginGroups>
<pluginGroup>com.your.plugins</pluginGroup>
</pluginGroups>

基于该配置Maven不仅会检查org/apache/maven/plugins/maven-metadata.xmlorg/codehaus/mojo/maven-metadata.xml 还会检查 com/your/plugins/maven-metadata.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<metadata>
<plugins>
<plugin>
<name>Apache Maven ACR Plugin</name>
<prefix>acr</prefix>
<artifactId>maven-acr-plugin</artifactId>
</plugin>
<plugin>
<name>Apache Maven Ant Plugin</name>
<prefix>ant</prefix>
<artifactId>maven-ant-plugin</artifactId>
</plugin>
</plugins>
</metadata>

prefix表示插件前缀,当Maven解析到类似dependency:tree命令时,先基于默认groupId归并所有插件仓库元数据,再检查归并后的元数据,根据prefix找到对应的artifactId,然后结合当前元数据的groupId解析得到version,就得到了完整的坐标。若org/apache/maven/plugins/maven-metadata.xml没有记录该插件前缀,则接着检查剩下的两个元数据。若所有元数据都不包含该前缀则报错