大多數電腦語言的學習都是從Hello World開始,我們通過建立一個在控制台列印Hello World字串的maven外掛程式來學習如何開發一個自訂maven外掛程式。
快速開發第一個外掛程式
1,建立一個maven-plugin目錄,並進入此目錄。
2,運行命令:
mvn archetype:create -DgroupId=com.ailbaba.maven -DartifactId=maven-hello-plugin -DarchetypeArtifactId=maven-archetype-mojo
可以看到建立一個工程,其pom.xml:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.alibaba.maven</groupId>
<artifactId>maven-hello-plugin</artifactId>
<packaging>maven-plugin</packaging>
<version>1.0-SNAPSHOT</version>
<name>maven-hello-plugin 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>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
3,進入maven-hello-plugin目錄,運行命令:mvn eclipse:eclipse構建eclipse工程。
4,通過eclipse import工程,刪除包下面自動產生的java檔案,建立HelloWorldMojo.java,HelloWorldMojo.java的內容如下:
package com.alibaba.maven;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
/**
* @goal helloworld
*/
public class HelloWorldMojo extends AbstractMojo {
/**
* @parameter expression="${helloworld.words}" default-value="Hello World!"
*/
private String words;
public void execute() throws MojoExecutionException {
getLog().info(words);
}
}
5, 檔案編寫完成後回到cmd命令列,在項目的pom檔案目錄處運行install命令將外掛程式安裝到本地repository:mvn clean install
6, 安裝成功後繼續運行如下命令查看外掛程式的運行情況:
運行:
mvn com.alibaba.maven:maven-hello-plugin:1.0-SNAPSHOT:helloworld
,可以看到控制台看到輸出:"Hello World!";這個輸出是外掛程式的預設參數:
default-value="Hello World!"
運行
mvn com.alibaba.maven:maven-hello-plugin:1.0-SNAPSHOT:helloworld -Dhelloworld.words="welcome!"
可以在控制台看到輸出:"welcome!";這個在命令中明確指定外掛程式的參數,因此輸出的是指定的參數"welcome!"。
關鍵點
1.maven的參數注入
maven預設使用的自行開發的Plexus,Plexus使用javadoc來管理依賴注入,可以看到上面的@goal,@parameter都是通過這種方式注入,現在看起來非常原始,不過maven3將遷移到guice.
2.MOJO
maven是由生命週期和goal完成任務的,比如maven install實際上包換了多種goal.外掛程式中的每個任務goal稱作一個 Mojo(Maven plain Old Java Object)。項目中每一個Mojo都要實現org.apache.maven.plugin.Mojo介面,上面的外掛程式樣本的Mojo通過擴充org.apache.maven.plugin.AbstractMojo類實現了該介面。Mojo提供如下的方法:
void setLog( org.apache.maven.monitor.logging.Log log)
當Maven載入並運行Mojo的時候,它會調用setLog()方法,為Mojo執行個體提供正確的日誌目標。
Mojo介面只關心兩件事情:目標運行結果的日誌記錄,以及運行一個目標。當編寫自訂外掛程式的時候,需要擴充AbstractMojo。 AbstractMojo處理setLog()和getLog()的實現,並包含一個抽象的execute()方法。在擴充AbstractMojo的時候,你所需要做的只是實現execute()方法。
公司maven-autoconfig-plugin探究
在你的本地倉庫會有maven autoconfig外掛程式的代碼,svn地址:http://svn.alibaba-inc.com/repos/ali_platform/maven/plugins/maven-autoconf-plugin/trunk,可以看一下核心類AutoconfMojo,其實裡面非常簡單:
/**
* Autoconf Mojo, eg: mvn autoconf:autoconf
*
* @goal autoconf
* @requiresProject false
*
* @author shawn.qianx
* @author hongyuan.zhouhy
* @author william.liangf
*/
public class AutoconfMojo extends AbstractMojo {
/**
* directory or jar/war/zip archive path, separate by comma, default is current directory.
*
* @parameter expression="${path}"
*/
private String path;
public void execute() throws MojoExecutionException, MojoFailureException {
getLog().info("Execute autoconf:autoconf.");
WarConfigRuntimeImpl runtime = new WarConfigRuntimeImpl(System.in, System.out, System.err, charset);
if(path != null && path.trim().length() > 0){
runtime.setDests(path.split(","));
} else {
runtime.setDests(new String[] {"."});
}
if (charset == null) {
charset = ConfigConstant.DEFAULT_CHARSET;
}
if (encoding == null) {
encoding = ConfigConstant.DEFAULT_CHARSET;
}
if (interactive) {
getLog().info("Turn on interactive mode.");
runtime.setInteractiveMode(ConfigConstant.INTERACTIVE_ON);
}
if (gui) {
runtime.setGuiMode();
}
if (verbose) {
runtime.setVerbose();
}
if(properties != null && properties.trim().length() > 0){
getLog().info("Customized user properties:" + properties + " using encoding:" + charset);
runtime.setUserPropertiesFile(properties, charset);
}
if (userProp != null && userProp.trim().length() > 0) {
getLog().info("Customized user properties:" + userProp + " using encoding:" + encoding);
runtime.setUserPropertiesFile(userProp, encoding);
}
if (sharedProperties != null && sharedProperties.length() > 0) {
getLog().info("Customized shared properties: " + descriptors);
runtime.setSharedPropertiesFiles(sharedProperties.split(","), sharedPropertiesName, charset);
}
if ((descriptors != null && descriptors.length() > 0)
|| (excludeDescriptors != null && excludeDescriptors.length() > 0)) {
String[] includes;
String[] excludes;
PatternSet patterns = runtime.getDescriptorPatterns();
if (descriptors == null || descriptors.length() == 0) {
try {
includes = patterns.getIncludes();
} catch (NullPointerException npe) {
includes = new String[0];
}
} else {
getLog().info("Customized include descriptors: " + descriptors);
includes = descriptors.split(",");
}
if (excludeDescriptors == null || excludeDescriptors.length() == 0) {
try {
excludes = patterns.getExcludes();
} catch (NullPointerException npe) {
excludes = new String[0];
}
} else {
getLog().info("Customized exclude descriptors: " + excludeDescriptors);
excludes = excludeDescriptors.split(",");
}
runtime.setDescriptorPatterns(includes, excludes);
}
if ((packages != null && packages.length() > 0)
|| (excludePackages != null && excludePackages.length() > 0)) {
String[] includes;
String[] excludes;
PatternSet patterns = runtime.getPackagePatterns();
if (packages == null || packages.length() == 0) {
try {
includes = patterns.getIncludes();
} catch (NullPointerException npe) {
includes = new String[0];
}
} else {
getLog().info("Customized include packages: " + descriptors);
includes = packages.split(",");
}
if (excludePackages == null || excludePackages.length() == 0) {
try {
excludes = patterns.getExcludes();
} catch (NullPointerException npe) {
excludes = new String[0];
}
} else {
getLog().info("Customized exclude packages: " + excludeDescriptors);
excludes = excludePackages.split(",");
}
runtime.setPackagePatterns(includes, excludes);
}
try {
runtime.start();
} catch (Exception e) {
runtime.error(e);
throw new MojoExecutionException("autoconf execution error", e);
}
}
}
小結
開發一個maven外掛程式就是開發一個mojo,然後這樣使用它們:maven xx:xx 。