編寫maven插件的步驟java
一:建立maven-plugin項目web
建立一個普通的maven項目,只是packaging改成maven-plugin,同時引入依賴maven-plugin-api。pom文件以下:sql
<?xml version="1.0" encoding="UTF-8"?> <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/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.sawyer.edu</groupId> <artifactId>maven-loc-plugin</artifactId> <version>1.0-SNAPSHOT</version> <packaging>maven-plugin</packaging> <properties> <maven.version>3.0</maven.version> </properties> <dependencies> <dependency> <groupId>org.apache.maven</groupId> <artifactId>maven-plugin-api</artifactId> <version>${maven.version}</version> </dependency> </dependencies> </project>
二:建立一個CountMojo類。該類所必要的三項工做:繼承AbstractMojo、實現execute()方法、提供@goal標註。代碼以下:express
package com.sawyer.edu.tlsys.plugin; import org.apache.maven.model.Resource; import org.apache.maven.plugin.AbstractMojo; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; import java.io.BufferedReader; import java.io.File; import java.io.FileReader; import java.io.IOException; import java.util.ArrayList; import java.util.List; /** * maven 代碼統計插件 * @author sawyer * @goal count */ public class CountMojo extends AbstractMojo { /** * default includes */ private static final String[] INCLUDES_DEFAULT = {"java", "xml", "properties"}; /** * @parameter expression = "${project.basedir}" * @required * @readonly */ private File basedir; /** * @parameter expression = "${project.build.sourceDirectory}" * @required * @readonly */ private File sourceDirectory; /** * @parameter expression = "${project.build.testSourceDirectory}" * @required * @readonly */ private File testSourceDirectory; /** * @parameter expression = "${project.build.resources}" * @required * @readonly */ private List<Resource> resources; /** * @parameter expression = "${project.build.testResources}" * @required * @readonly */ private List<Resource> testResources; /** * file types which will be included for counting * @parameter */ private String[] includes; /** * execute * @throws MojoExecutionException MojoExecutionException * @throws MojoFailureException MojoFailureException */ public void execute() throws MojoExecutionException, MojoFailureException { if(includes == null || includes.length == 0){ includes = INCLUDES_DEFAULT; } try{ countDir(sourceDirectory); countDir(testSourceDirectory); for(Resource resource : resources){ countDir(new File(resource.getDirectory())); } for(Resource testResource : testResources){ countDir(new File(testResource.getDirectory())); } }catch (Exception e){ throw new MojoExecutionException("count failed:", e); } } /** * 統計某個目錄下文件的代碼行 * @param dir 目錄 * @throws IOException 文件異常 */ private void countDir (File dir) throws IOException{ if(!dir.exists()){ return; } List<File> collected = new ArrayList<File>(); collectFiles(collected, dir); int lines = 0; for(File sourceFile : collected){ lines += countLine(sourceFile); } String path = dir.getAbsolutePath().substring(basedir.getAbsolutePath().length()); getLog().info(path + ": " + lines + " lines of code in " + collected.size() + "files"); } /** * 遞歸獲取文件列表 * @param collected 文件列表list * @param file 文件 */ private void collectFiles(List<File> collected, File file){ if(file.isFile()){ for(String include : includes){ if(file.getName().endsWith("." + include)){ collected.add(file); break; } } }else{ for(File sub : file.listFiles()){ collectFiles(collected, sub); } } } /** * 讀取文件的行數 * @param file 文件對象 * @return line * @throws IOException 文件操做異常 */ private int countLine(File file) throws IOException{ BufferedReader reader = new BufferedReader(new FileReader(file)); int line = 0; try{ while(reader.ready()){ reader.readLine(); line++; } }finally { reader.close(); } return line; } }
這裏要關注的是@goal標註,這個標註就是這個類的目標,定義了目標以後,咱們才能夠在項目中配置該插件目標。apache
代碼中還包含了basedir、sourceDirectory、testSourceDirectory等字段,它們都使用了@parameter標註,同時關鍵字expression表示從系統屬性中讀取這幾個字段值。api
其次,代碼中的includes字段就是用來爲用戶提供該配置點的,它的類型爲String數組,而且使用了@parameter參數表示用戶能夠本身在pom中配置該字段,使用該插件時的pom配置以下:數組
<plugin>
<groupId>com.iflytek.edu</groupId>
<artifactId>maven-loc-plugin</artifactId>
<version>1.0-SNAPSHOT</version>
<configuration>
<includes>
<include>java</include>
<include>sql</include>
</includes>
</configuration>
<executions>
<execution>
<phase>compile</phase>
<goals>
<goal>count</goal>
</goals>
</execution>
</executions>
</plugin>
根據上面的pom配置,能夠看到incuudes字段標識須要統計的文件後綴,phase表示該插件在compile階段工做,使用該插件的時候能夠看到以下輸出信息:app
[INFO] --- maven-loc-plugin:1.0-SNAPSHOT:count (default) @ ZX-jobmonitor-webapp --- [INFO] \src\main\java: 778 lines of code in 6files [INFO] \src\test\java: 0 lines of code in 0files [INFO] \src\main\resources: 0 lines of code in 0files
使用mvn clean install命令將該插件項目構建並安裝到本地倉庫後,並按照上面的pom配置,就能夠使用它統計項目的代碼了。webapp
三:錯誤處理和日誌maven
上面的CountMojo類繼承自AbstratctMojo,跟蹤會發現該抽象類實現了類Mojo接口,execute()方法就是在這個接口中定義的。
void execute() throws MojoExecutionException, MojoFailureException;
這個方法能夠拋出兩種異常,
若是是MojoFailureException異常,則表示爲發現了預期的錯誤,例如單元測試插件在發現測試失敗時就會拋出該異常。
若是是MojoExcutionException異常,則表示發現了未預期的異常,例如上述代碼中的IOException等。
四:測試
可在項目中直接集成該插件,也能夠在項目目錄下用命令行來測試該插件,命令以下:
mvn com.sawyer.edu:maven-loc-plugin:1.0-SNAPSHOT:count