Maven插件编写

一般步骤

  • 创建maven-plugin项目,打包方式必须为maven-plugin,可使用maven-archetype-plugin快速创建
  • 编写插件目标,每个插件必须包含一个或多个目标,必须提供一个或多个继承自AbstractMojo的类
  • 为目标提供配置点,编写Mojo时提供可配置的参数。
  • 编写代码实现目标行为,根据实际需要实现Mojo
  • 错误处理及日志,当Mojo异常时,根据情况控制Maven的运行状态
  • 测试插件,编写自动化测试代码测试行为,再实际运行插件验证其行为

案例

每个插件目标即Mojo都必须继承AbstractMojo并实现execute()方法,这样Maven才能识别该插件,并执行execute()方法中的行为。当在execute()方法捕获的其他异常时,使用MojoExecutionException对其简单包装后再抛出,Maven执行插件目标时遇到MojoExecutionException会在命令行显示BUILD ERROR.

标注实现方式

maven-plugin-api该依赖中包含了插件开发所必需的类。

1
2
3
4
5
6
7
8
9
10
11
12
13
<modelVersion>4.0.0</modelVersion>
<groupId>com.long.mvnbook.account</groupId>
<artifactId>account-maven-plugin</artifactId>
<packaging>maven-plugin</packaging>
<name>Maven Mojo</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-plugin-api</artifactId>
<version>2.0</version>
</dependency>
</dependencies>

默认使用的是Java1.4风格的标注

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/**
* @goal touch
* @phase process-sources
*/
public class MyMojo extends AbstractMojo {
/**
* @parameter expression="${project.build.directory}"
* @required
*/
private File outputDirectory;

/**
* @parameter
*/
private String[] includes;

public void execute() throws MojoExecutionException {
}
}
注解实现方式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<modelVersion>4.0.0</modelVersion>
<groupId>com.long.mvnbook.account</groupId>
<artifactId>account-maven-plugin</artifactId>
<packaging>maven-plugin</packaging>
<name>Maven Mojo</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-core</artifactId>
<version>3.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.maven.plugin-tools</groupId>
<artifactId>maven-plugin-annotations</artifactId>
<version>3.0</version>
<scope>provided</scope>
</dependency>
</dependencies>

使用注解的方式,具体实现代码示例

1
2
3
4
5
6
7
8
9
10
11
12
13
@Mojo(name = "touch", defaultPhase = LifecyclePhase.PROCESS_SOURCES)
@Execute(goal = "", phase = "", lifecycle = "")
public class MyMojo extends AbstractMojo {

@Parameter(defaultValue = "${project.build.directory}", required = true)
private File outputDirectory;

@parameter
private String[] includes;

public void execute() throws MojoExecutionException {
}
}
使用插件
1
2
3
4
5
6
7
8
9
10
<plugin>
<groupId>com.long.mvnbook.account</groupId>
<artifactId>account-maven-plugin</artifactId>
<configuration>
<includes>
<include></include>
<include></include>
</includes>
</configuration>
</plugin>

Mojo标注

  • @goal <name> 每个Mojo都必须使用该标注注明目标名称,对应注解方式@Mojo(name = "")
  • @phase <phase> 将目标绑定至Default生命周期的某个阶段
  • @requiresDependencyResolution <scope> 运行该Mojo前必须解析所有指定范围的依赖,默认为runtime
  • @requiresProject <true/false> 该目标是否必须在Maven项目中运行
  • @requiresDirectInvocation <true/false> 是否只能通过命令行调用
  • @requiresOnline <true/false> 是否要求Maven必须是在线状态,默认false
  • @requiresReports <true/false> 是否要求项目报告已经生成,默认false
  • @aggregator 在多模块项目中,表示只会在顶层模块中运行
  • @execute goal = "<goal>" 运行该目标前先运行另一个目标,本插件目标直接使用目标名,否则使用prefix:goal
  • @execute phase= "<phase>" 运行该目标前线运行一个并行的生命周期到指定阶段
  • @execute lifecycle= "<lifecycle>" 运行该目标前线运行一个自定义生命周期到指定阶段

Mojo参数

可以使用@parameter将Mojo的某个字段标注为可配置的参数即Mojo参数。Maven支持BooleanIntegerFloatStringDateFileURL多值数组CollectionMapProperties等多种Mojo参数。

Boolean
1
2
3
4
@parameter     
private boolean sampleBoolean;
// 对应配置
<sampleBoolean>true</sampleBoolean>
Integer
1
2
3
4
@parameter     
private int sampleInt;
// 对应配置
<sampleInt>6</sampleInt>
Float
1
2
3
4
@parameter     
private int sampleFloat;
// 对应配置
<sampleFloat>6.5</sampleFloat>
String
1
2
3
4
@parameter     
private int sampleString;
// 对应配置
<sampleString>HW</sampleString>
Date
1
2
3
4
5
@parameter     
private int sampleDate;
// 对应配置,格式为yyyy-MM-dd HH:mm:ss.Sa或yyyy-MM-dd HH:mm:ssa
<sampleDate>2019-03-03 11:28:55.1 PM</sampleDate>
<sampleDate>2019-03-03 11:28:55PM</sampleDate>
File
1
2
3
4
@parameter     
private int sampleFile;
// 对应配置
<sampleFile>c:\tmp</sampleFile>
URL
1
2
3
4
@parameter     
private int sampleURL;
// 对应配置
<sampleURL>https://yaoyinglong.github.io</sampleURL>
数组
1
2
3
4
5
6
7
@parameter     
private String[] includes;
// 对应配置
<includes>
<include></include>
<include></include>
</includes>
Collection
1
2
3
4
5
6
7
@parameter     
private List includes;
// 对应配置
<includes>
<include></include>
<include></include>
</includes>
Map
1
2
3
4
5
6
7
@parameter     
private Map sampleMap;
// 对应配置
<sampleMap>
<key1></key1>
<key2></key2>
</sampleMap>
Properties
1
2
3
4
5
6
7
8
9
10
11
12
13
@parameter     
private Properties sampleProperties;
// 对应配置
<sampleProperties>
<properties>
<name></name>
<value></value>
</properties>
<properties>
<name></name>
<value></value>
</properties>
</sampleProperties>

除此之外@parameter还提供一些额外的属性

  • @parameter alias = ""给参数配置别名
  • @parameter expression= "${aSystemProperty}"使用系统属性表达式给参数赋值
  • @parameter default-value= "aValue/${anExpression}"若未配置才参数,就提供一个默认值
  • @readonly 参数只读
  • @required 必须参数