天天看點

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");
    }
}
           

效果:

Maven插件開發

參考:

1.https://www.runoob.com/maven/maven-build-life-cycle.html

2.https://blog.csdn.net/zjf280441589/article/details/53044308