Maven是一款基于插件作业的构建工具,它自身内置了非常多我们平常开发所需要的插件。如清理资源插件maven-clean-plugin
,编译插件maven-compiler-plugin
,打包插件maven-jar-plugin
等。在工作中,我们也可以开发自己的插件,帮助我们提高开发效率
下方以开发一个统计目录下所有文件的内容行数的插件为例
创建Maven插件项目 使用archetypemaven-archetype-mojo
创建一个Maven项目(对应的groupid为org.apache.maven.archetypes
)
项目名最好使用name-maven-plugin
,这样后续可以直接使用name:goal来执行插件目标
如下图,IDEA创建了一个count-maven-plugin
项目
修改POM文件 IDEA自动创建的项目中,maven-plugin-api
版本是2.0,太低了。我的Maven版本是3.6.3,所以这里我也把maven-plugin-api
版本改成3.6.3
同时,我们加入maven-plugin-annotations
依赖,这样开发时可以使用maven注解。同时,我们修改项目的JDK版本为1.8。最终的pom.xml文件如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 <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.creasy.maven.plugins</groupId > <artifactId > count-maven-plugin</artifactId > <packaging > maven-plugin</packaging > <version > 1.0-SNAPSHOT</version > <name > count-maven-plugin Maven Mojo</name > <url > http://maven.apache.org</url > <properties > <maven.compiler.source > 1.8</maven.compiler.source > <maven.compiler.target > 1.8</maven.compiler.target > </properties > <dependencies > <dependency > <groupId > org.apache.maven</groupId > <artifactId > maven-plugin-api</artifactId > <version > 3.6.3</version > </dependency > <dependency > <groupId > junit</groupId > <artifactId > junit</artifactId > <version > 3.8.1</version > <scope > test</scope > </dependency > <dependency > <groupId > org.apache.maven.plugin-tools</groupId > <artifactId > maven-plugin-annotations</artifactId > <version > 3.6.2</version > <scope > provided</scope > </dependency > </dependencies > </project >
添加goal对应的类 项目默认创建了一个MyMojo
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 package com.creasy.maven.plugins;import org.apache.maven.plugin.AbstractMojo;import org.apache.maven.plugin.MojoExecutionException;import java.io.File;import java.io.FileWriter;import java.io.IOException;public class MyMojo extends AbstractMojo { private File outputDirectory; public void execute () throws MojoExecutionException { File f = outputDirectory; if ( !f.exists() ) { f.mkdirs(); } File touch = new File( f, "touch.txt" ); FileWriter w = null ; try { w = new FileWriter( touch ); w.write( "touch.txt" ); } catch ( IOException e ) { throw new MojoExecutionException( "Error creating file " + touch, e ); } finally { if ( w != null ) { try { w.close(); } catch ( IOException e ) { } } } } }
这个类很简单,就是在outputDirectory(对应目录为${project.build.directory}
,也就是常见的maven项目的target目录)目录下创建一个touch.txt文件,文件内容为touch.txt
我们参考MyMojo创建一个CountMojo类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 package com.creasy.maven.plugins;import org.apache.maven.model.Resource;import org.apache.maven.plugin.AbstractMojo;import org.apache.maven.plugin.MojoExecutionException;import org.apache.maven.plugins.annotations.LifecyclePhase;import org.apache.maven.plugins.annotations.Mojo;import org.apache.maven.plugins.annotations.Parameter;import java.io.BufferedReader;import java.io.File;import java.io.FileReader;import java.io.IOException;import java.util.ArrayList;import java.util.List;import java.util.Objects;@Mojo(name = "count",//对应插件的goal defaultPhase = LifecyclePhase.COMPILE,//绑定Maven的生命周期的默认值 requiresProject = true, threadSafe = true) public class CountMojo extends AbstractMojo { @Parameter(defaultValue = "${project.build.sourceDirectory}") private File sourceDirectory; @Parameter(defaultValue = "${project.build.testSourceDirectory}") private File testSourceDirectory; @Parameter(defaultValue = "${project.resources}") private List<Resource> resources; @Parameter(defaultValue = "${project.testResources}") private List<Resource> testResources; public void execute () throws MojoExecutionException { try { countLine(sourceDirectory); countLine(testSourceDirectory); for (Resource resource : resources) { countLine(new File(resource.getDirectory())); } for (Resource testResource : testResources) { countLine(new File(testResource.getDirectory())); } } catch (IOException e) { throw new MojoExecutionException("Unable to count line!" , e); } } private void countLine (File dir) throws IOException { if ( dir.exists() ){ List<File> files = getFileByDir(dir); long line = 0 ; for (File file : files) { line += countFile(file); } getLog().info(String.format("Directory:%s, lines:%s" , dir.getPath(), line)); } } private List<File> getFileByDir (File dir) { List<File> retList = new ArrayList<>(); for (File file : Objects.requireNonNull(dir.listFiles())) { if (file.isDirectory()) { retList.addAll(getFileByDir(file)); } else { retList.add(file); } } return retList; } private long countFile (File f) throws IOException { long retValue = 0 ; try (BufferedReader bufferedReader = new BufferedReader(new FileReader(f))) { while (null != bufferedReader.readLine()) { retValue++; } } return retValue; } }
这个类还是比较简单的,有几点内容说明下
@Parameter(defaultValue = "${project.build.sourceDirectory}")
类中的变量可以通过@Parameter注解,定义使用插件时可以传参,如果不传则默认使用项目的${project.build.sourceDirectory}
属性。project.build.sourceDirectory这个属性其实是在super POM中定义的,具体可以使用的变量参考这里
类必须继承AbstractMojo,实现execute接口
需要使用@Mojo注解的name属性定义goal
以上,执行mvn clean install
,即可把项目安装到本地仓库
使用插件 其他项目要使用插件,只需要在pom文件中添加
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 <build > <plugins > <plugin > <groupId > com.creasy.maven.plugins</groupId > <artifactId > count-maven-plugin</artifactId > <version > 1.0-SNAPSHOT</version > <executions > <execution > <goals > <goal > count</goal > </goals > </execution > </executions > </plugin > </plugins > </build >
因为count默认绑定了compile生命周期,所以这里至配置了插件的goal
执行mvn clean compile
,如下,插件输出了每个资源目录下所有文件的内容行数
参考文档:
https://maven.apache.org/guides/plugin/guide-java-plugin-development.html
https://maven.apache.org/pom.html