虽然,平时工作基本用不到自定义插件,但手动实现一遍还是很有必要.
这样在配置和调用Maven
插件时才能做到知其所以然.
所以本文的标题其实应该是:当我们在使用Maven
插件时我们在使用什么.
简单来说,实现自定义插件,只需要继承maven-plugin-api
工程中的AbastractMojo
并实现无参抽象方法execute
即可.
不过这还不够,因为还需要考虑goal
,phase
和入参等操作.
有两种方式来定义:
1️⃣ JavaDoc
方式
2️⃣ 注解方式: 推荐使用.
使用IDEA可以很方便创建Maven
插件项目:
命名项目:maven-plugin-demo
;
等待工程生成完成,pom.xml
已经引入maven-plugin-api
,同时还生成了一个以JavaDoc
方式实现的自定义插件示例(详见文末附录),故不再赘述,而是以注解形式实现一个自定义插件,它的作用很简单,只是接收参数并打印.
首先引入包含注解的依赖(别忘了还有maven-plugin-api
):
<dependency>
<groupId>org.apache.maven.plugin-toolsgroupId>
<artifactId>maven-plugin-annotationsartifactId>
<version>3.5.2version>
dependency>
继承AbstractMojo
:
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
@Mojo(name = "hello", defaultPhase = LifecyclePhase.PROCESS_CLASSES)
public class AnnoMojo extends AbstractMojo {
@Parameter(property = "hello.message", required = true, defaultValue = "${project.name}")
private String[] message;
@Override
public void execute() throws MojoExecutionException, MojoFailureException {
System.out.println("hello " + String.join("", message) + "~");
}
}
此时插件已经开发完成.
引入依赖
<build>
<plugins>
<plugin>
<groupId>org.examplegroupId>
<artifactId>maven-plugin-demoartifactId>
<version>1.0-SNAPSHOTversion>
plugin>
plugins>
build>
执行mvn -Dhello.message=world,~~ demo:hello
即可实现打印出hello world~~~
的效果.
但一般不会这样显式地单独调用,而是靠clean
,compile
或deploy
等Lifecycle
来触发,其触发关键点在于插件所附着的phase
,它们是有固定的先后顺序的,可以参考官网.
<plugin>
<groupId>org.examplegroupId>
<artifactId>maven-plugin-demoartifactId>
<version>1.0-SNAPSHOTversion>
<executions>
<execution>
<goals>
<goal>hellogoal>
goals>
<phase>process-sourcesphase>
execution>
executions>
<configuration>
<message>every body! I'm Ryanmessage>
configuration>
plugin>
此时执行mvn compile
就会触发插件的hello
目标并打印输出:hello every body! I'm Ryan~
.
executions
元素可以有多个execution
,用来绑定一个phase
和多个goal
.configuration
元素用来配置插件中定义的parameter
上节中提到了configuration
用来静态配置变量,而命令行可以动态设置,如果同时设置,谁的优先级更高呢?
答案是configuration
元素.
同理,pom
中定义的phase
的优先级高于源码中定义的defaultPhase
maven-plugin-XXX
,可以简化命令行调用:mvn XXX:$goal
maven-plugin
pom.xml
中已定义的参数configuration
中设置.默认生成的源码:
/**
* Goal which touches a timestamp file.
*
* @goal touch
* @phase process-sources
*/
public class MyMojo extends AbstractMojo {
/**
* Location of the file.
*
* @parameter expression="${project.build.directory}"
* @required
*/
private File outputDirectory;
public void execute() throws MojoExecutionException {
// 此处忽略具体实现
}
}