前言
雖然,平時工作基本用不到自定義插件,但手動實現一遍還是很有必要.
這樣在配置和調用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-tools</groupId>
<artifactId>maven-plugin-annotations</artifactId>
<version>3.5.2</version>
</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.example</groupId>
<artifactId>maven-plugin-demo</artifactId>
<version>1.0-SNAPSHOT</version>
</plugin>
</plugins>
</build>
執行mvn -Dhello.message=world,~~ demo:hello
即可實現打印出hello world~~~
的效果.
但一般不會這樣顯式地單獨調用,而是靠clean
,compile
或deploy
等Lifecycle
來觸發,其觸發關鍵點在於插件所附着的phase
,它們是有固定的先後順序的,可以參考官網.
<plugin>
<groupId>org.example</groupId>
<artifactId>maven-plugin-demo</artifactId>
<version>1.0-SNAPSHOT</version>
<executions>
<execution>
<goals>
<goal>hello</goal>
</goals>
<phase>process-sources</phase>
</execution>
</executions>
<configuration>
<message>every body! I'm Ryan</message>
</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
- packaging:
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 { // 此處忽略具體實現 } }