首页 > 学院 > 开发设计 > 正文

编写maven代码行统计插件

2019-11-15 00:16:27
字体:
来源:转载
供稿:网友
编写maven代码行统计插件

编写maven插件的步骤

  1. 创建一个maven-plugin项目:插件本身也是maven项目,只是它的packaging是maven-plugin。
  2. 为插件编写目标:每个插件必须包含一个或多个目标,maven称之为Mojo。编写插件时必须提供一个或多个继承自AbstractMojo的类。
  3. 为目标提供配置点:大部分maven插件以及其目标都是可配置的,因此在编写Mojo的时候需要注意提供可配置的参数。
  4. 编写代码,实现目标。
  5. 错误处理以及日志,为客户提供足够的信息。
  6. 测试插件

一:创建maven-plugin项目

创建一个普通的maven项目,只是packaging改为maven-plugin,同时引入依赖maven-plugin-api。pom文件如下:

<?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标注。代码如下:

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;    }}
CountMojo代码

这里要关注的是@goal标注,这个标注就是这个类的目标,定义了目标之后,我们才可以在项目中配置该插件目标。

代码中还包含了basedir、sourceDirectory、testSourceDirectory等字段,它们都使用了@parameter标注,同时关键字expression表示从系统属性中读取这几个字段值。

其次,代码中的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阶段工作,使用该插件的时候可以看到如下输出信息:

[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配置,就可以使用它统计项目的代码了。

三:错误处理和日志

上面的CountMojo类继承自AbstratctMojo,跟踪会发现该抽象类实现了类Mojo接口,execute()方法就是在这个接口中定义的。

void execute()        throws MojoExecutionException, MojoFailureException;

这个方法可以抛出两种异常,

如果是MojoFailureException异常,则表示为发现了预期的错误,例如单元测试插件在发现测试失败时就会抛出该异常。

如果是MojoExcutionException异常,则表示发现了未预期的异常,例如上述代码中的IOException等。

四:测试

可在项目中直接集成该插件,也可以在项目目录下用命令行来测试该插件,命令如下:

mvn com.sawyer.edu:maven-loc-plugin:1.0-SNAPSHOT:count


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表