閱讀625 返回首頁    go 阿裏雲 go 技術社區[雲棲]


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;
02  
03 import org.apache.maven.plugin.AbstractMojo;
04 import org.apache.maven.plugin.MojoExecutionException;
05 import org.apache.maven.plugins.annotations.Mojo;
06  
07 /**
08  * Says "Hi" to the user.
09  *
10  */
11 @Mojo( name = "sayhi")
12 public class GreetingMojo extends AbstractMojo
13 {
14     public void execute() throws MojoExecutionException
15     {
16         getLog().info( "Hello, world." );
17     }
18 }
  • 類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示例,參數按上表要求設定:

01 <project>
02   <modelVersion>4.0.0</modelVersion>
03  
04   <groupId>sample.plugin</groupId>
05   <artifactId>hello-maven-plugin</artifactId>
06   <version>1.0-SNAPSHOT</version>
07   <packaging>maven-plugin</packaging>
08  
09   <name>Sample Parameter-less Maven Plugin</name>
10  
11   <dependencies>
12     <dependency>
13       <groupId>org.apache.maven</groupId>
14       <artifactId>maven-plugin-api</artifactId>
15       <version>3.0</version>
16     </dependency>
17  
18     <!-- dependencies to annotations -->
19     <dependency>
20       <groupId>org.apache.maven.plugin-tools</groupId>
21       <artifactId>maven-plugin-annotations</artifactId>
22       <version>3.4</version>
23       <scope>provided</scope>
24     </dependency>
25   </dependencies>
26 </project>

構建目標

在maven-plugin中定義了很少幾個目標作為標準構建生命周期的一部分:

compile 編譯插件的Java代碼,構建插件描述
test 運行插件的單元測試
package 構建插件jar包
install 將插件jar安裝到本地倉庫
deploy 將插件jar部署到遠程倉庫

執行你的第一個Mojo

執行新插件的最直接方式是在命令行直接指定插件目標。要這樣做,你需要在項目中這樣配置hello-Maven-plugin:

01 ...
02   <build>
03     <plugins>
04       <plugin>
05         <groupId>sample.plugin</groupId>
06         <artifactId>hello-maven-plugin</artifactId>
07         <version>1.0-SNAPSHOT</version>
08       </plugin>
09     </plugins>
10   </build>
11 ...

然後,指定目標的全名:

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中增加如下配置:
    1 <pluginGroups>
    2   <pluginGroup>sample.plugin</pluginGroup>
    3 </pluginGroups>

此時,可以用”mvn hello:sayhi”運行Mojo了。

將Mojo關聯到構建生命周期

你也可以配置插件關聯到構建生命周期某個特定階段的指定目標,示例如下:

01 <build>
02    <plugins>
03      <plugin>
04        <groupId>sample.plugin</groupId>
05        <artifactId>hello-maven-plugin</artifactId>
06        <version>1.0-SNAPSHOT</version>
07        <executions>
08          <execution>
09            <phase>compile</phase>
10            <goals>
11              <goal>sayhi</goal>
12            </goals>
13          </execution>
14        </executions>
15      </plugin>
16    </plugins>
17  </build>

這樣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示例:

1 /**
2     * The greeting to display.
3     */
4    @Parameter( property = "sayhi.greeting", defaultValue = "Hello World!" )
5    private String greeting;

注解之前的部分是參數說明。參數注解將變量聲明為Mojo參數。注解的defaultValue參數定義了變量的默認值。這個值可以包含引用項目變量的表達式,如”{project.version}”(在  “Parameter Expressions” document能看到更多)。property參數支持引用用戶在命令行中通過-D指定的係統屬性。

在項目中配置參數

作為插件定義的一部分,插件的參數值配置在Maven項目的pom.xml中完成,示例:

1 <plugin>
2   <groupId>sample.plugin</groupId>
3   <artifactId>hello-maven-plugin</artifactId>
4   <version>1.0-SNAPSHOT</version>
5   <configuration>
6     <greeting>Welcome</greeting>
7   </configuration>
8 </plugin>

在configuration部分,名為”greeting”的元素名是參數的名稱,元素的值”Welcome”是賦予參數的值。
注意:更多細節參見 Guide to Configuring Plugins

單值參數類型

下麵是可作為Mojo參數的簡單變量類型及其值在pom中的解釋規則。

Boolean

包括boolean和Boolean。讀配置時,讀到true字符串時將參數設為true,讀到其它字符串將參數設為false。例如:

1 /**
2     * My boolean.
3     */
4    @Parameter
5    private boolean myBoolean;
1 <myBoolean>true</myBoolean>
定點數

包括byte, Byte, int, Integer, long, Long, short和Short。讀配置時,xml中的文本通過Integer.parseInt()或對應類型的valueOf()方法轉為整型數。字符串必須是有效的十進製整數,隻包含數字0到9和可選的前置“-”表示負數。例如:

1 /**
2     * My Integer.
3     */
4    @Parameter
5    private Integer myInteger;
1 <myInteger>10</myInteger>
浮點數

包含double, Double, float和Float。讀配置時,使用對應類型的valueOf()將xml中的文本轉為二進製。文本可以是Java語言規範3.10.2節規定的任意格式。有效值示例如1.0和6.02E+23。

1 /**
2     * My Double.
3     */
4    @Parameter
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 /**
2     * My Date.
3     */
4    @Parameter
5    private Date myDate;
1 <myDate>2005-10-06 2:22:55.1 PM</myDate>
文件和目錄

包括File類。讀配置時,xml文件中的文本被當做需要的文件或目錄路徑。如果是相對路徑(不以/或驅動器字母如C:開頭),路徑是相對於POM所在目錄。例如:

1 /**
2     * My File.
3     */
4    @Parameter
5    private File myFile;
1 <myFile>c:\temp</myFile>
URL

包含URL類。讀配置時,xml中的文本被當做URL。格式必須遵循RFC2396,看起來像web瀏覽器的URL(scheme://host:port/path/to/file)。轉換URL時對它的任何部分沒有限製。

1 /**
2    * My URL.
3    */
4   @Parameter
5   private URL myURL;
普通文本

包含char, Character, StringBuffer和String。讀配置時,xml文件中的文本被當做賦予參數的值。對char和Character參數,隻使用文本的第一個字符。

枚舉

也可以使用枚舉類型變量。首先需要定義枚舉類型,然後就可以在參數定義中使用了。

01 public enum Color {
02      GREEN,
03      RED,
04      BLUE
05    }
06  
07    /**
08     * My Enum
09     */
10    @Parameter
11    private Color myColor;

在pom配置中可以使用這樣的枚舉:

1 <myColor>GREEN</myColor>

也可以使用枚舉類型的元素作為默認值,像下麵這樣:

01 public enum Color {
02      GREEN,
03      RED,
04      BLUE
05    }
06  
07    /**
08     * My Enum
09     */
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中的文本將被轉換為恰當的對象。

數組

數組參數通過多次指定來配置,例如:

1 /**
2     * My Array.
3     */
4    @Parameter
5    private String[] myArray;
1 <myArray>
2   <param>value1</param>
3   <param>value2</param>
4 </myArray>
集合

這一類包含所有實現java.util.Collection的類,如ArrayList或HashSet。這些參數也像數組一樣通過多次指定來配置,例如:

1 /**
2     * My List.
3     */
4    @Parameter
5    private List myList;
1 <myList>
2   <param>value1</param>
3   <param>value2</param>
4 </myList>

關於獨立集合元素的映射細節,查看 Mapping Lists.。

映射

這一類包含所有實現java.util.Map而未實現java.util.Properties的類,如HashMap。這些參數通過包含XML標簽來配置,形如<key>value</key>,例如:

1 /**
2   * My Map.
3   */
4  @Parameter
5  private Map myMap;
1 <myMap>
2   <key1>value1</key1>
3   <key2>value2</key2>
4 </myMap>

Properties
這一類包含所有實現java.util.Properties的映射。這些參數通過包含XML標簽配置,形如<property><name>myName</name> <value>myValue</value> </property>,例如:

1 /**
2   * My Properties.
3   */
4  @Parameter
5  private Properties myProperties;
01 <myProperties>
02   <property>
03     <name>propertyName1</name>
04     <value>propertyValue1</value>
05   <property>
06   <property>
07     <name>propertyName2</name>
08     <value>propertyValue2</value>
09   <property>
10 </myProperties>

其它對象類型
這一類包含所有未實現java.util.Map、java.util.Collection和java.util.Dictionary的類。例如:

1 /**
2     * My Object.
3     */
4    @Parameter
5    private MyObject myObject;
1 <myObject>
2   <myField>test</myField>
3 </myObject>

查看 Mapping Complex Objects了解更多配置這種參數的策略細節。

使用setters

如果你想在Maven上下文之外重用Mojo,私有屬性映射是好選擇,對它的使用沒有限製。按上麵的示例我們可以使用下劃線風格命名私有屬性,並提供setter供配置映射機製使用,Mojo看起來是這樣的:

01 public class MyQueryMojo
02     extends AbstractMojo
03 {
04     @Parameter(property="url")
05     private String _url;
06  
07     @Parameter(property="timeout")
08     private int _timeout;
09  
10     @Parameter(property="options")
11     private String[] _options;
12  
13     public void setUrl( String url )
14     {
15         _url = url;
16     }
17  
18     public void setTimeout( int timeout )
19     {
20         _timeout = timeout;
21     }
22  
23     public void setOptions( String[] options )
24     {
25         _options = options;
26     }
27  
28     public void execute()
29         throws MojoExecutionException
30     {
31         ...
32     }
33 }

注意當屬性名和插件配置中實際的參數名不一致時,對參數對應的屬性名的標記,這是用來告知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

  上一篇:go  《架構真經:互聯網技術架構的設計》水平擴展
  下一篇:go  《架構真經:互聯網技術架構的設計》分而治之