625
阿裏雲
技術社區[雲棲]
Maven的Java插件開發指南
本指南的目標是幫助用戶使用Java開發Maven插件。
重要聲明:插件命名規範和Apache Maven商標
通常將你的插件命名為<yourplugin>-maven-plugin。
強烈反對命名為maven-<yourplugin>-plugin(maven在插件名開頭),因為這是Apache Maven組織為官方Maven插件保留的命名格式,用org.apache.maven.plugins作為組id。使用此命名是對Apache Maven商標的侵權。
你的第一個插件
這一部分我們將構建一個不帶參數、運行時輸出一行信息的簡單插件,會覆蓋創建插件項目的基本操作、Java Mojo的核心內容,以及執行Mojo的兩種方式。
你的第一個Mojo
最簡單地,一個Java Mojo隻包含一個類。不需要像EJB有多個類,盡管包含一組相似Mojo的插件很可能提取一個抽象基類以合並公共代碼。
在代碼樹中搜索Mojo時,plugin-tools尋找帶有@Mojo形式的Java5注解的類或帶有goal的javadoc型注解。所有帶有這樣注解的類包含在插件配置文件中。
一個簡單的Mojo
下麵是一個簡單的無參數Mojo類,它可能是最簡單的Mojo了。代碼示例後麵是各部分的說明。
01 |
package sample.plugin;
|
03 |
import org.apache.maven.plugin.AbstractMojo;
|
04 |
import org.apache.maven.plugin.MojoExecutionException;
|
05 |
import org.apache.maven.plugins.annotations.Mojo;
|
08 |
* Says "Hi" to the user.
|
11 |
@Mojo ( name = "sayhi" )
|
12 |
public class GreetingMojo extends AbstractMojo
|
14 |
public void execute() throws MojoExecutionException
|
16 |
getLog().info( "Hello, world." );
|
- 類org.apache.maven.plugin.AbstractMojo提供了實現一個Mojo需要的大部分基礎功能,除了execute方法。
- “@Mojo”注解是必須的,它控製了Mojo何時和怎樣被執行
- execute方法可以拋出兩種異常:
- org.apache.Maven.plugin.MojoExecutionException 如果發生了非預期的錯誤拋出此異常,顯示”BUILD ERROR”信息。
- org.apache.Maven.plugin.MojoFailureException 如果發生了預期內的錯誤(例如編譯錯誤)拋出此異常,顯示“BUILD FAILURE”信息。
- getLog方法(在AbstractMojo中定義)返回一個類似log4j的日誌對象,插件可以用它輸出debug, info, warn, error級別的日誌。這個日誌是用戶可接受的顯示信息的方式。查看Retrieving the Mojo Logger 了解如何恰當使用。
所有的Mojo注解在 Mojo API Specification中描述。
項目定義
插件的Mojo寫完後,就可以構建插件了。插件描述中需要設置以下幾項:
groupId |
插件的組id,應當與Mojo包名的共同前綴一致 |
artifactId |
插件名 |
version |
插件版本 |
packaging |
應設為”maven-plugin” |
dependencies |
必須聲明對Maven Plugin Tools API的依賴以解析”AbstractMojo”和相關類 |
下麵是示例Mojo的pom示例,參數按上表要求設定:
02 |
<modelVersion>4.0.0</modelVersion>
|
04 |
<groupId>sample.plugin</groupId>
|
05 |
<artifactId>hello-maven-plugin</artifactId>
|
06 |
<version>1.0-SNAPSHOT</version>
|
07 |
<packaging>maven-plugin</packaging>
|
09 |
<name>Sample Parameter-less Maven Plugin</name>
|
13 |
<groupId>org.apache.maven</groupId>
|
14 |
<artifactId>maven-plugin-api</artifactId>
|
15 |
<version>3.0</version>
|
18 |
<!-- dependencies to annotations -->
|
20 |
<groupId>org.apache.maven.plugin-tools</groupId>
|
21 |
<artifactId>maven-plugin-annotations</artifactId>
|
22 |
<version>3.4</version>
|
23 |
<scope>provided</scope>
|
構建目標
在maven-plugin中定義了很少幾個目標作為標準構建生命周期的一部分:
compile |
編譯插件的Java代碼,構建插件描述 |
test |
運行插件的單元測試 |
package |
構建插件jar包 |
install |
將插件jar安裝到本地倉庫 |
deploy |
將插件jar部署到遠程倉庫 |
執行你的第一個Mojo
執行新插件的最直接方式是在命令行直接指定插件目標。要這樣做,你需要在項目中這樣配置hello-Maven-plugin:
05 |
<groupId>sample.plugin</groupId>
|
06 |
<artifactId>hello-maven-plugin</artifactId>
|
07 |
<version>1.0-SNAPSHOT</version>
|
然後,指定目標的全名:
1 |
mvn groupId:artifactId:version:goal |
例如,要運行示例插件的Mojo,在命令行輸入“mvn sample.plugin:hello-Maven-plugin:1.0-SNAPSHOT:sayhi”。
注:運行單一目標不需要指定版本。
縮短命令行
有幾種方式縮短輸入:
- 如果運行本地倉庫安裝的最新版插件,可以省略版本號。使用”mvn sample.plugin:hello-Maven-plugin:sayhi”運行。
- 賦予插件一個短前綴,如mvn hello:sayhi。如果按照${prefix}-maven-plugin的命名方式(如果插件是Apache Maven的官方插件用maven-${prefix}-plugin)這是自動完成的。也可以通過額外的配置設置前綴,更多信息參見Introduction to Plugin Prefix Mapping。
- 最後,可以把插件的組id加入默認搜索的組id列表。這種方式需要在${user.home}/.m2/settings.xml中增加如下配置:
2 |
<pluginGroup>sample.plugin</pluginGroup>
|
此時,可以用”mvn hello:sayhi”運行Mojo了。
將Mojo關聯到構建生命周期
你也可以配置插件關聯到構建生命周期某個特定階段的指定目標,示例如下:
04 |
<groupId>sample.plugin</groupId>
|
05 |
<artifactId>hello-maven-plugin</artifactId>
|
06 |
<version>1.0-SNAPSHOT</version>
|
09 |
<phase>compile</phase>
|
這樣Java代碼編譯時這個簡單Mojo就會執行。更多綁定Mojo到生命周期階段的信息,參考 Build Lifecycle。
Mojo原型
利用Mojo原型創建新插件項目:
1 |
mvn archetype:generate \ |
2 |
-DgroupId=sample.plugin \
|
3 |
-DartifactId=hello-maven-plugin \
|
4 |
-DarchetypeGroupId=org.apache.maven.archetypes \
|
5 |
-DarchetypeArtifactId=maven-archetype-plugin
|
參數
不帶參數的Mojo一般沒太大用處,參數提供了以下重要功能:
- 提供了讓用戶調整插件操作以適應應用的鉤子
- 提供一種不需要導航到對象就能提取POM元素值的簡單方式
定義Mojo參數
定義一個參數很簡單,隻需要在Mojo中創建一個實例變量並增加恰當的注解。以下是帶參數的簡單Mojo示例:
2 |
* The greeting to display.
|
4 |
@Parameter ( property = "sayhi.greeting" , defaultValue = "Hello World!" )
|
5 |
private String greeting;
|
注解之前的部分是參數說明。參數注解將變量聲明為Mojo參數。注解的defaultValue參數定義了變量的默認值。這個值可以包含引用項目變量的表達式,如”{project.version}”(在 “Parameter Expressions” document能看到更多)。property參數支持引用用戶在命令行中通過-D指定的係統屬性。
在項目中配置參數
作為插件定義的一部分,插件的參數值配置在Maven項目的pom.xml中完成,示例:
2 |
<groupId>sample.plugin</groupId>
|
3 |
<artifactId>hello-maven-plugin</artifactId>
|
4 |
<version>1.0-SNAPSHOT</version>
|
6 |
<greeting>Welcome</greeting>
|
在configuration部分,名為”greeting”的元素名是參數的名稱,元素的值”Welcome”是賦予參數的值。
注意:更多細節參見 Guide to Configuring Plugins。
單值參數類型
下麵是可作為Mojo參數的簡單變量類型及其值在pom中的解釋規則。
Boolean
包括boolean和Boolean。讀配置時,讀到true字符串時將參數設為true,讀到其它字符串將參數設為false。例如:
5 |
private boolean myBoolean;
|
1 |
<myBoolean>true</myBoolean> |
定點數
包括byte, Byte, int, Integer, long, Long, short和Short。讀配置時,xml中的文本通過Integer.parseInt()或對應類型的valueOf()方法轉為整型數。字符串必須是有效的十進製整數,隻包含數字0到9和可選的前置“-”表示負數。例如:
5 |
private Integer myInteger;
|
1 |
<myInteger>10</myInteger> |
浮點數
包含double, Double, float和Float。讀配置時,使用對應類型的valueOf()將xml中的文本轉為二進製。文本可以是Java語言規範3.10.2節規定的任意格式。有效值示例如1.0和6.02E+23。
5 |
private Double myDouble;
|
1 |
<myDouble>1.0</myDouble> |
日期
包括Date類型。讀配置時,xml中的文本按”yyyy-MM-dd HH:mm:ss.S a”(如”2005-10-06 2:22:55.1 PM”)或”yyyy-MM-dd HH:mm:ssa”(如”2005-10-06 2:22:55PM”)格式轉換。注意解析通過DateFormat.parse()完成,允許格式的少許偏差。這個方法盡力解析出日期和時間,即使格式不嚴格地匹配上述格式,例如:
1 |
<myDate>2005-10-06 2:22:55.1 PM</myDate> |
文件和目錄
包括File類。讀配置時,xml文件中的文本被當做需要的文件或目錄路徑。如果是相對路徑(不以/或驅動器字母如C:開頭),路徑是相對於POM所在目錄。例如:
1 |
<myFile>c:\temp</myFile> |
URL
包含URL類。讀配置時,xml中的文本被當做URL。格式必須遵循RFC2396,看起來像web瀏覽器的URL(scheme://host:port/path/to/file)。轉換URL時對它的任何部分沒有限製。
普通文本
包含char, Character, StringBuffer和String。讀配置時,xml文件中的文本被當做賦予參數的值。對char和Character參數,隻使用文本的第一個字符。
枚舉
也可以使用枚舉類型變量。首先需要定義枚舉類型,然後就可以在參數定義中使用了。
11 |
private Color myColor;
|
在pom配置中可以使用這樣的枚舉:
1 |
<myColor>GREEN</myColor> |
也可以使用枚舉類型的元素作為默認值,像下麵這樣:
10 |
@Parameter (defaultValue = "GREEN" )
|
11 |
private Color myColor;
|
多值參數類型
下麵介紹可以在Mojo中作為參數使用的各種複合對象,及它們在POM中的解釋規則。一般來說,保存參數值(和參數值中的元素)的對象的類型是按以下步驟決定的(確定有效類型的第一步):
1. 如果XML元素包含implementation屬性,就使用它
2. 如果XML標簽包含”.”,嚐試解析為類的全名
3. 嚐試將XML標簽(首字母大寫)解析為Mojo所在包中的類
4. 對數組,使用數組的元素類型(例如,對String[]參數使用String類型);對集合和映射,使用Mojo配置中指定的類;使用String作為集合類型的entry和map的值的類型。
一旦元素的類型確定了,xml中的文本將被轉換為恰當的對象。
數組
數組參數通過多次指定來配置,例如:
5 |
private String[] myArray;
|
集合
這一類包含所有實現java.util.Collection的類,如ArrayList或HashSet。這些參數也像數組一樣通過多次指定來配置,例如:
關於獨立集合元素的映射細節,查看 Mapping Lists.。
映射
這一類包含所有實現java.util.Map而未實現java.util.Properties的類,如HashMap。這些參數通過包含XML標簽來配置,形如<key>value</key>,例如:
Properties
這一類包含所有實現java.util.Properties的映射。這些參數通過包含XML標簽配置,形如<property><name>myName</name> <value>myValue</value> </property>,例如:
5 |
private Properties myProperties;
|
03 |
<name>propertyName1</name>
|
04 |
<value>propertyValue1</value>
|
07 |
<name>propertyName2</name>
|
08 |
<value>propertyValue2</value>
|
其它對象類型
這一類包含所有未實現java.util.Map、java.util.Collection和java.util.Dictionary的類。例如:
5 |
private MyObject myObject;
|
2 |
<myField>test</myField>
|
查看 Mapping Complex Objects了解更多配置這種參數的策略細節。
使用setters
如果你想在Maven上下文之外重用Mojo,私有屬性映射是好選擇,對它的使用沒有限製。按上麵的示例我們可以使用下劃線風格命名私有屬性,並提供setter供配置映射機製使用,Mojo看起來是這樣的:
01 |
public class MyQueryMojo
|
04 |
@Parameter (property= "url" )
|
07 |
@Parameter (property= "timeout" )
|
10 |
@Parameter (property= "options" )
|
11 |
private String[] _options;
|
13 |
public void setUrl( String url )
|
18 |
public void setTimeout( int timeout )
|
23 |
public void setOptions( String[] options )
|
29 |
throws MojoExecutionException
|
注意當屬性名和插件配置中實際的參數名不一致時,對參數對應的屬性名的標記,這是用來告知Maven要使用的getter和setter。
資源
1. Mojo Documentation: Mojo API,Mojo注解
2. Maven Plugin Testing Harness: Mojo測試框架
3. Plexus: Maven使用的IoC容器
4. Plexus Common Utilities: 對Mojo開發有用的工具類集合
5. Commons IO: 對文件/路徑操作有用的工具類集合
6. Common Bugs and Pitfalls: 錯誤的代碼模式概覽
轉載自 並發編程網 - ifeve.com
最後更新:2017-05-19 15:32:20