Maven插件开发

概述:
通过开发一个简单的maven插件来更深入的了解maven

maven:
maven是一个包管理和插件调度框架,所有的功能(如编译、打包、发布)都是由插件完成的。

maven有30个阶段,这30个阶段(phase)分别归属于3个标准的生命周期,所有的插件都需要绑定到其中一个阶段执行(插件本身可以设置默认阶段,pom.xml中也可以重新绑定插件的阶段,最后是可以在执行mvn命令时绑定插件的阶段)。编译时调用某个阶段,该阶段及在该阶段所属的生命周期前的所有阶段都会被执行,如,执行clean,那么pre-clean,clean都会被执行。可以看作在maven内部有一个模板方法,指定一个阶段时,该阶段的方法,以及该阶段前的所有方法都会执行。

3个标准生命周期及30个阶段(@See org.apache.maven.plugins.annotations.LifecyclePhase):

clean: pre-clean,clean,post-clean

build(默认的生命周期): validate,initialize,generate-sources,process-sources,generate-resources,process-resources,compile,process-classes,generate-test-sources,process-test-sources,generate-test-resources,process-test-resources,test-compile,process-test-classes,test,prepare-package,package,pre-integration-test,integration-test,post-integration-test,verify,install,deploy

site: pre-site,site,post-site,site-deploy


步骤:
1.打开命令行,执行以下命令,创建一个插件项目(该项目本身也是一个maven项目):

mvn archetype:generate -DgroupId=com.study.maven.plugins -DartifactId=line-count -Dversion=0.0.1-SNAPSHOT -DarchetypeArtifactId=maven-archetype-plugin -DinteractiveMode=false -DarchetypeCatalog=internal

其中(-D后是输入参数):
groupId的值用于指定pom.xml中的groupId
artifactId的值用于指定pom.xml中的artifactId
version的值用于指定pom.xml中的version
其它参数照抄就行

2.编写插件代码

(见代码)

3.使用插件
在要使用该插件的项目的pom.xml文件中的<build>下<plugins>下添加如下配置:

            <plugin>
                <groupId>com.study.maven.plugins</groupId>
                <artifactId>line-count</artifactId>
                <version>0.0.1-SNAPSHOT</version>
                <executions>
                    <execution>
                        <id>count</id>
                        <!--重新绑定插件的phase-->
                        <phase>install</phase>
                        <goals>
                            <goal>count</goal>
                        </goals>
                        <!--配置参数-->
                        <configuration>
                            <fileType>java</fileType>
                            <minSpaceNum>10</minSpaceNum>
                            <countRelBaseDir>./src</countRelBaseDir>
                        </configuration>
                    </execution>
                </executions>
            </plugin>

代码:
配置文件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.study.maven.plugins</groupId>
    <artifactId>line-count</artifactId>
    <packaging>maven-plugin</packaging>
    <version>0.0.1-SNAPSHOT</version>
    <!--指定使用的jdk版本-->
    <profiles>
        <profile>
            <id>jdk-1.8</id>
            <activation>
                <jdk>1.8</jdk>
                <activeByDefault>true</activeByDefault>
            </activation>
            <properties>
                <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
                <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
                <maven.compiler.encoding>UTF-8</maven.compiler.encoding>
                <maven.compiler.source>1.8</maven.compiler.source>
                <maven.compiler.target>1.8</maven.compiler.target>
                <maven.compiler.compilerVersion>1.8</maven.compiler.compilerVersion>
            </properties>
        </profile>
    </profiles>
    <name>line-count 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>
        <!--引入maven插件的注解-->
        <dependency>
            <groupId>org.apache.maven.plugin-tools</groupId>
            <artifactId>maven-plugin-annotations</artifactId>
            <version>3.5</version>
        </dependency>
    </dependencies>
</project>

文件行数信息FileLineInfo:

package com.study.maven.plugins;

public class FileLineInfo {
    private String filePath;
    private Integer lineCount;

    public FileLineInfo(String filePath, Integer lineCount) {
        this.filePath = filePath;
        this.lineCount = lineCount;
    }

    public String getFilePath() {
        return filePath;
    }

    public void setFilePath(String filePath) {
        this.filePath = filePath;
    }

    public Integer getLineCount() {
        return lineCount;
    }

    public void setLineCount(Integer lineCount) {
        this.lineCount = lineCount;
    }
}

字符串工具类MyStringUtils:

package com.study.maven.plugins;

public class MyStringUtils {
    public static boolean isBlank(String str) {
        return !isNotBlank(str);
    }

    public static boolean isNotBlank(String str) {
        return str != null && !str.isEmpty() && containsText(str);
    }

    private static boolean containsText(CharSequence str) {
        int strLen = str.length();
        for (int i = 0; i < strLen; ++i) {
            if (!Character.isWhitespace(str.charAt(i))) {
                return true;
            }
        }
        return false;
    }
}

插件类MyMojo:

package com.study.maven.plugins;

/*
 * Copyright 2001-2005 The Apache Software Foundation.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.logging.Log;
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.net.URLEncoder;
import java.util.*;

/**
 * Goal which touches a timestamp file.
 *
 * @goal touch
 * @phase process-sources
 */
@Mojo(name = "count", defaultPhase = LifecyclePhase.COMPILE)
public class MyMojo extends AbstractMojo {
    private static final Set<String> DEFAULT_FILE_TYPE = new HashSet<String>(Arrays.asList("java", "xml", "properties"));
    private static final String EMPTY_STRING = "";
    private static final String DOT = ".";
    private static final String SEPARATOR = "------------------------------------------------------------------------";
    private static final String UTF8 = "utf-8";
    private static final int DEFAULT_MIN_SPACE_NUM = 5;

    @Parameter(defaultValue = "${project.build.countRelBaseDir}", readonly = true)
    private String countRelBaseDir;

    private String countBaseDir;

    private String countBaseDirEncoder;

    @Parameter(defaultValue = "${project.build.fileType}", readonly = true)
    private String fileType;

    @Parameter(defaultValue = "${project.build.minSpaceNum}", readonly = true)
    private Integer minSpaceNum;

    private Set<String> fileTypeSet;

    private int maxFilePathLen = 0;

    private Log log = getLog();

    public void execute() throws MojoExecutionException {
        boolean isSuccess = true;
        long totalLineCount = 0;
        try {
            init();
            List<File> files = new ArrayList<>();
            getFiles(files);
            List<FileLineInfo> fileLineInfos = getFileLineInfo(files);
            totalLineCount = formatPrint(fileLineInfos);
        } catch (Exception e) {
            isSuccess = false;
            e.printStackTrace();
        }
        endPointPrint(isSuccess, totalLineCount);
    }

    private void endPointPrint(boolean isSuccess, long totalLineCount) {
        log.info(SEPARATOR);
        if (isSuccess) {
            log.info("COUNT SUCCESS -> TOTAL LINE COUNT: " + totalLineCount);
        } else {
            log.info("COUNT FAIL");
        }
        log.info(SEPARATOR);
    }

    private long formatPrint(List<FileLineInfo> fileLineInfos) {
        long totalLineCount = 0;
        for (FileLineInfo fileLineInfo : fileLineInfos) {
            totalLineCount += fileLineInfo.getLineCount();
            log.info(getFormetLine(fileLineInfo));
        }
        return totalLineCount;
    }

    private String getFormetLine(FileLineInfo fileLineInfo) {
        int spaceNum = maxFilePathLen + minSpaceNum - fileLineInfo.getFilePath().length();
        StringBuilder formatLine = new StringBuilder(fileLineInfo.getFilePath());
        while (spaceNum > 0) {
            spaceNum--;
            formatLine.append(DOT);
        }
        formatLine.append(fileLineInfo.getLineCount());
        return formatLine.toString();
    }

    private List<FileLineInfo> getFileLineInfo(List<File> files) throws IOException {
        List<FileLineInfo> fileLineInfos = new ArrayList<>();
        for (File file : files) {
            String filePath = file.getCanonicalPath().replaceFirst(countBaseDirEncoder, EMPTY_STRING);
            Integer lineCount = countLine(file);
            fileLineInfos.add(new FileLineInfo(filePath, lineCount));
            maxFilePathLen = Math.max(maxFilePathLen, filePath.length());
        }
        return fileLineInfos;
    }

    private Integer countLine(File file) {
        int count = 0;
        try (FileReader fr = new FileReader(file); BufferedReader br = new BufferedReader(fr)) {
            String line;
            while ((line = br.readLine()) != null) {
                if (MyStringUtils.isNotBlank(line.trim())) {
                    count++;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return count;
    }

    private void getFiles(List<File> files) throws IOException {
        File baseDir = new File(countBaseDir);
        doGetFiles(baseDir, files);
    }

    private void doGetFiles(File currentFile, List<File> files) throws IOException {
        if (currentFile.isDirectory()) {
            File[] subs = currentFile.listFiles();
            for (File sub : subs) {
                doGetFiles(sub, files);
            }
        } else {
            if (fileTypeSet.contains(getFileType(currentFile))) {
                files.add(currentFile);
            }
        }
    }

    private String getFileType(File file) throws IOException {
        String path = file.getCanonicalPath();
        if (MyStringUtils.isBlank(path)) {
            return EMPTY_STRING;
        }
        int lastIndexOf = path.lastIndexOf(".");
        if (lastIndexOf == -1) {
            return EMPTY_STRING;
        }
        if (lastIndexOf < path.length() - 1) {
            return path.substring(lastIndexOf + 1);
        }
        return EMPTY_STRING;
    }

    private void init() throws IOException {
        countBaseDir = getProjectDir();
        if (MyStringUtils.isNotBlank(countRelBaseDir)) {
            File file = new File(countBaseDir.concat(File.separator).concat(countRelBaseDir));
            countBaseDir = file.getCanonicalPath();
        }
        countBaseDirEncoder = URLEncoder.encode(countBaseDir, UTF8);
        log.info("-----countBaseDir:" + countBaseDir);
        if (MyStringUtils.isBlank(fileType)) {
            fileTypeSet = DEFAULT_FILE_TYPE;
        } else {
            fileTypeSet = new HashSet<>(Arrays.asList(fileType.trim().split(",")));
        }
        log.info("-----fileTypeSet:" + fileTypeSet);
        if (minSpaceNum == null || minSpaceNum < 0) {
            minSpaceNum = DEFAULT_MIN_SPACE_NUM;
        }
        log.info("-----minSpaceNum:" + minSpaceNum);
    }

    private String getProjectDir() {
        return System.getProperty("user.dir");
    }
}

效果:

参考:
1.https://www.runoob.com/maven/maven-build-life-cycle.html
2.https://blog.csdn.net/zjf280441589/article/details/53044308

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值