C:\Users\chengxiang.peng.QUNARSERVERS\MavenSources>mvn archetype:generate [INFO] Scanning for projects... [INFO] [INFO] ------------------------------------------------------------------------ [INFO] Building Maven Stub Project (No POM) 1 [INFO] ------------------------------------------------------------------------ [INFO] [INFO] >>> maven-archetype-plugin:2.4:generate (default-cli) > generate-sources@ standalone-pom >>> [INFO] [INFO] <<< maven-archetype-plugin:2.4:generate (default-cli) < generate-sources@ standalone-pom <<< [INFO] [INFO] --- maven-archetype-plugin:2.4:generate (default-cli) @ standalone-pom --- [INFO] Generating project in Interactive mode ... ... 1713: remote -> us.fatehi:schemacrawler-archetype-plugin-dbconnector (-) 1714: remote -> us.fatehi:schemacrawler-archetype-plugin-lint (-) Choose a number or apply filter (format: [groupId:]artifactId, case sensitive contains): 876: maven-archetype-plugin Choose archetype: 1: remote -> org.apache.maven.archetypes:maven-archetype-plugin (An archetype which contains a sample Maven plugin.) 2: remote -> org.apache.maven.archetypes:maven-archetype-plugin-site (An archetype which contains a sample Maven plugin site. This archetype can be layered upon an existing Maven plugin project.) Choose a number or apply filter (format: [groupId:]artifactId, case sensitive contains): : 1 Choose org.apache.maven.archetypes:maven-archetype-plugin version: 1: 1.0 2: 1.1 3: 1.2 Choose a number: 3: 3 Define value for property 'groupId': : com.chengxiang.maven Define value for property 'artifactId': : maven-plugin Define value for property 'version': 1.0-SNAPSHOT: : Define value for property 'package': com.chengxiang.maven: : maven-plugin Confirm properties configuration: groupId: com.chengxiang.maven artifactId: maven-plugin version: 1.0-SNAPSHOT package: maven-plugin Y: : Y [INFO] ---------------------------------------------------------------------------- [INFO] Using following parameters for creating project from Archetype: maven-archetype-plugin:1.2 [INFO] ---------------------------------------------------------------------------- [INFO] Parameter: groupId, Value: com.chengxiang.maven [INFO] Parameter: artifactId, Value: maven-plugin [INFO] Parameter: version, Value: 1.0-SNAPSHOT [INFO] Parameter: package, Value: maven-plugin [INFO] Parameter: packageInPathFormat, Value: maven-plugin [INFO] Parameter: package, Value: maven-plugin [INFO] Parameter: version, Value: 1.0-SNAPSHOT [INFO] Parameter: groupId, Value: com.chengxiang.maven [INFO] Parameter: artifactId, Value: maven-plugin [INFO] project created from Archetype in dir: C:\Users\chengxiang.peng.QUNARSERVERS\MavenSources\maven-plugin [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 02:31 min [INFO] Finished at: 2016-10-16T23:39:06+08:00 [INFO] Final Memory: 14M/172M [INFO] ------------------------------------------------------------------------2.为插件编写目标、配置点和目标行为,处理相关错误日志:每个插件都包含一个或者多个目标,故必须提供一个或者多个继承AbstractMojo类;可视具体情况提供可配置的参数;根据具体目标实现execute()方法逻辑;
/** * CountMojo:每个插件的目标类都需要继承AbstractMojo,并实现execute()方法 * Created by chengxiang.peng on 2016/10/17. * "@goal":标注来写明自己的目标名称 * @goal count */ public class CountMojo extends AbstractMojo { //默认统计Java,xml和properties文件 private static final String[] INCLUDES_DEFAULT = {"java", "xml", "properties"}; /** * "expression":从系统属性读取这几个字段;"@readonly":不允许用户进行配置 * 项目基础目录 * @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; /** * "@parameter":使用该插件的时候,可以配置该参数 * 计算的代码行数的类型范围 * @parameter */ private String[] includes; public void execute() throws MojoExecutionException { //如果没有配置类型范围,则使用默认的类型范围 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 resource : testResources) { countDir(new File(resource.getDirectory())); } } catch (IOException e) { //异常转译,将IO异常转换成Mojo定义的异常抛出 throw new MojoExecutionException("Unable to count lines of code.", e); } } /** * 统计指定目录下文件的代码行数 * @param dir 统计的指定目录 * @throws IOException 不处理IO异常,抛出给外部处理 */ 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); } //输出统计结果:AbstractMojo的getLog()方法返回日志对象,输出Maven日志 String path = dir.getAbsolutePath().substring(basedir.getAbsolutePath().length()); getLog().info(path + ": " + lines + " lines of code in " + collected.size() + " files"); } /** * 遍历查找目标目录了中指定类型的文件,并保存在集合中 * @param collected 指定类型文件集合 * @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 代码行数 * @throws IOException 不处理IO异常,抛出给外部处理 */ 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; } }3.上传和测试插件:适用mvn clean install命令,将编写完成的插件,上传在本地库中,然后在实际运行该插件验证其行为;
C:\Users\chengxiang.peng.QUNARSERVERS\MavenSources\mavenplugin>mvn clean install [INFO] Scanning for projects... [INFO] [INFO] ------------------------------------------------------------------------ [INFO] Building mavenplugin Maven Plugin 1.0-SNAPSHOT [INFO] ------------------------------------------------------------------------ [INFO] [INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ mavenplugin --- [INFO] Deleting C:\Users\chengxiang.peng.QUNARSERVERS\MavenSources\mavenplugin\target [INFO] [INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ mavenplugin --- [INFO] Using 'UTF-8' encoding to copy filtered resources. [INFO] skip non existing resourceDirectory C:\Users\chengxiang.peng.QUNARSERVERS\MavenSources\mavenplugin\src\main\resources [INFO] [INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ mavenplugin --- [INFO] Changes detected - recompiling the module! [INFO] Compiling 1 source file to C:\Users\chengxiang.peng.QUNARSERVERS\MavenSources\mavenplugin\target\classes [INFO] [INFO] --- maven-plugin-plugin:3.2:descriptor (default-descriptor) @ mavenplugin --- [INFO] Using 'UTF-8' encoding to read mojo metadata. [INFO] Applying mojo extractor for language: java //Maven版本升级,@parameter expression="${property}"写法过时,可升级按照说明更新写法 [WARNING] mavenplugin.CountMojo#basedir: [WARNING] The syntax [WARNING] @parameter expression="${property}" [WARNING] is deprecated, please use [WARNING] @parameter property="property" [WARNING] instead. [WARNING] mavenplugin.CountMojo#resources: [WARNING] The syntax [WARNING] @parameter expression="${property}" [WARNING] is deprecated, please use [WARNING] @parameter property="property" [WARNING] instead. [WARNING] mavenplugin.CountMojo#sourceDirectory: [WARNING] The syntax [WARNING] @parameter expression="${property}" [WARNING] is deprecated, please use [WARNING] @parameter property="property" [WARNING] instead. [WARNING] mavenplugin.CountMojo#testResources: [WARNING] The syntax [WARNING] @parameter expression="${property}" [WARNING] is deprecated, please use [WARNING] @parameter property="property" [WARNING] instead. [WARNING] mavenplugin.CountMojo#testSourceDirectory: [WARNING] The syntax [WARNING] @parameter expression="${property}" [WARNING] is deprecated, please use [WARNING] @parameter property="property" [WARNING] instead. [INFO] Mojo extractor for language: java found 1 mojo descriptors. [INFO] Applying mojo extractor for language: bsh [INFO] Mojo extractor for language: bsh found 0 mojo descriptors. [INFO] Applying mojo extractor for language: java-annotations [INFO] Mojo extractor for language: java-annotations found 0 mojo descriptors. [INFO] [INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ mavenplugin --- [INFO] Using 'UTF-8' encoding to copy filtered resources. [INFO] skip non existing resourceDirectory C:\Users\chengxiang.peng.QUNARSERVERS\MavenSources\mavenplugin\src\test\resources [INFO] [INFO] --- maven-compiler-plugin:3.1:testCompile (default-testCompile) @ mavenplugin --- [INFO] No sources to compile [INFO] [INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ mavenplugin --- [INFO] No tests to run. [INFO] [INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ mavenplugin --- [INFO] Building jar: C:\Users\chengxiang.peng.QUNARSERVERS\MavenSources\mavenplugin\target\mavenplugin-1.0-SNAPSHOT.jar [INFO] [INFO] --- maven-plugin-plugin:3.2:addPluginArtifactMetadata (default-addPluginArtifactMetadata) @ mavenplugin --- [INFO] //插件构建完毕后,上传到本地仓库后 [INFO] --- maven-install-plugin:2.4:install (default-install) @ mavenplugin --- [INFO] Installing C:\Users\chengxiang.peng.QUNARSERVERS\MavenSources\mavenplugin\target\mavenplugin-1.0-SNAPSHOT.jar to C:\Users\chengxiang.peng.QUNARSERVERS\.m2\repository\com\chengxiang\mavenplugin\1.0-SNAPSHOT\mavenplugin-1.0-SNAPSHOT.jar [INFO] Installing C:\Users\chengxiang.peng.QUNARSERVERS\MavenSources\mavenplugin\pom.xml to C:\Users\chengxiang.peng.QUNARSERVERS\.m2\repository\com\chengxiang\mavenplugin\1.0-SNAPSHOT\mavenplugin-1.0-SNAPSHOT.pom [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 3.798 s [INFO] Finished at: 2016-10-17T17:54:56+08:00 [INFO] Final Memory: 20M/171M [INFO] ------------------------------------------------------------------------在当前的项目目录下,执行编写插件的目标;
C:\Users\chengxiang.peng.QUNARSERVERS\MavenSources\mavenplugin>mvn com.chengxiang:mavenplugin:1.0-SNAPSHOT:count [INFO] Scanning for projects... Downloading: http://svn.corp.qunar.com:8081/nexus/content/groups/public/com/chengxiang/mavenplugin/1.0-SNAPSHOT/maven-metadata.xml Downloading: http://l-digging7.wap.cn8.qunar.com:8086/content/repositories/thirdparty/com/chengxiang/mavenplugin/1.0-SNAPSHOT/maven-metadata.xml [INFO] [INFO] ------------------------------------------------------------------------ [INFO] Building mavenplugin Maven Plugin 1.0-SNAPSHOT [INFO] ------------------------------------------------------------------------ [INFO] //插件输出结果 [INFO] --- mavenplugin:1.0-SNAPSHOT:count (default-cli) @ mavenplugin --- [INFO] \src\main\java: 165 lines of code in 1 files [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 1.472 s [INFO] Finished at: 2016-10-17T18:17:31+08:00 [INFO] Final Memory: 7M/155M [INFO] ------------------------------------------------------------------------
二、Mojo标注
标注 |
说明 |
备注 |
@goal<name> |
目标名称 |
唯一必须声明;命令调用、POM配置插件时候使用; |
@phase<phase> |
目标绑定的生命周期阶段 |
默认至Default阶段 |
@requiresDependencyResolution<scope> |
运行目标前必须解析所有指定范围的依赖 |
如maven-surefire-plugin的test带有@requiresDependencyResolution test标识在执行测试之前,所有测试范围的依赖都必须解析 |
@requiresProject<true/false> |
目标是否必须在一个Maven项目中运行 |
默认true,如maven-help-plugin的system目标,显示系统属性和环境变量,不需要实际项目 |
@requiresDirectInvocation<true/false> |
目标只能通过命令调用 |
默认为false,如果视图在POM中将其绑定到生命周期阶段,Maven就会报错 |
@requiresOnline<true/false> |
是否要求Maven必须在线状态 |
默认false |
@requiresReport<true/false> |
是否要求项目报告已经生成 |
默认false |
@aggregator |
当在多模块项目运行时,标识䯮只会在顶层模块运行 |
如maven-javadoc-plugin的aggregator-jar使用了该标注,多模块时只会在顶层项目生成一个聚合的javadoc文档 |
@execute goal="<goal>" |
在运行目标前先让maven运行另外一个目标 |
如果是本插件的目标,则直接使用目标名称,否则使用“prefix:goal”形式 |
@execute phase="<phase>" |
在运行目标运行一个并行的生命周期,到指定的阶段为止。 |
如maven-dependency-plugin的analyze使用了标注@execute phase="test-compile",当执行dependency:analyze的时候,会首先执行default生命周期至test-compile阶段 |
@execute lifecycle="<lifecycle>" phase="<phase>" |
运行目标之前先运行一个自定义的生命周期,到指定的阶段为止。 |
如maven-surefire-report-plugin插件report目标,标注了@execute phase="test" lifecycle="surefire",表示运行这个自定义的surefire生命周期至test阶段 |
/** *@parameter */ private boolean sampleBoolean; 配置: <sampleBoolean>true</sampleBoolean>2.int(包括Integer、long、Long、short、Short、byte、Byte):
/** *@parameter */ private int sampleInt; 配置: <sampleInt>8</sampleInt>3.float(包括Float、double、Double):
/** *@parameter */ private int sampleFloat; 配置: <sampleFloat>8.8</sampleFloat>4.String(包括StringBuffer、char、Character):
/** *@parameter */ private String sampleString; 配置: <sampleString>8</sampleString>5.Date(格式为yyy-MM-dd HH:mm:ss Sa)
/** *@parameter */ private Date sampleDate; 配置: <sampleDate>2010-06-06 3:14:55.1 PM</sampleDate>6.File
/** *@parameter */ private File sampleFile; 配置: <sampleFile>c:\tmp</sampleFile>7.URL
/** *@parameter */ private URL sampleURL; 配置: <sampleURL>http://www.qunar.com</sampleURL>8.数组
/** *@parameter */ private String[] includes; 配置: <includes> <include>java</include> <include>sql</include> </includes>9.Collection(任何实现Collection接口的类,如ArrayList和HashSet)
/** *@parameter */ private List includes; 配置: <includes> <include>java</include> <include>sql</include> </includes>10.Map
/** *@parameter */ private Map sampleMap; 配置: <sampleMap> <key>value1</key> <key>value2</key> </sampleMap>11.Properties
/** *@parameter */ private Properties sampleProperties; 配置: <sampleProperties> <samplePropertie> <name>p_name_1</name> <value>p_value_1</value> </samplePropertie> <samplePropertie> <name>p_name_2</name> <value>p_value_2</value> </samplePropertie> </sampleProperties>12.@parameter alias="<aliasName>"
/** *@parameter alias="uid" */ private String uniqueIndentity; 配置: <uid>user_1</uid>13.@parameter expression="${aSystemProperty}"
/** *@parameter expression="${maven.test.skip}" */ private boolean skip;14.@parameter defaultValue="aValue/${anExpression}"
/** *@parameter defaultValue="true" */ private boolean sampleBoolean;15.@readonly