如何编写一个maven插件

873 阅读1分钟

本文食用导航

  • 基础介绍
  • 实战demo
  • 参考资料

基础介绍

maven依赖

我们开发的maven插件也是一个maven-plugin,所以需要依赖maven官方提供的plugin的api

...
<!-- 特别注意打包方式必须为maven-plugin -->
<packaging>maven-plugin</packaging>

<dependencies>
    <dependency> <!--使用doc的方式-->
        <groupId>org.apache.maven</groupId>
        <artifactId>maven-plugin-api</artifactId>
        <version>3.6.1</version>
    </dependency>
    <dependency> <!--使用注解的方式-->
        <groupId>org.apache.maven.plugin-tools</groupId>
        <artifactId>maven-plugin-annotations</artifactId>
        <version>3.6.1</version>
    </dependency>
</dependencies>

...

插件类 AbstractMojo

Mojo 实际上只是Maven 中的一个目标,插件由任意数量的目标 (Mojo) 组成。Mojo 可以定义为带注释的 Java 类或 Beanshell 脚本。Mojo 指定有关目标的元数据:目标名称、它适合的生命周期阶段以及它期望的参数。

该类的 execute 方法会执行构建行为,我们可以在该方法中定义我们自己的逻辑。

如何编写

基于注解的方式

@Mojo(name = "annotationTest")
public abstract class AnnotationTestMojo extends AbstractMojo {


    @Parameter(property = "version", defaultValue = "${project.version}", required = true, readonly = true)
    private String version;

    /**
     * 简单的输出maven项目的版本号
     */
    public void execute() {
        Log log = getLog();
        log.info(String.format("my project version : %s", version));
    }
}
  • @Mojo标识了该类能被maven-plugin扫描到,成为一个插件类,其中name属性全局唯一,是这个Mojo的身份标识。

  • @Parameter:property属性支持在pom中获取到自己的自定义属性值,defaultValue是给予 该属性一个默认的值,支持EL表达式。

<build>
    <plugins>
        <plugin>
            ...
            <configuration> <!-- 自定义属性信息 -->
                <version>${project.version}</version>
            </configuration>
            ...
        </plugin>
    </plugins>
</build>

构建与打包

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-plugin-plugin</artifactId>
            <version>3.6.1</version>            <!-- 插件执行命令前缀 -->
            <configuration>
                <goalPrefix>mymaven-plugin-demo</goalPrefix>
                <skipErrorNoDescriptorsFound>true</skipErrorNoDescriptorsFound>
            </configuration>
        </plugin>
    </plugins>
</build>

如何使用

引入依赖

<build>
    <plugins>
        <plugin>
            <groupId>xx.xx</groupId>
            <artifactId>maven-plugin-demo</artifactId>
            <version>1.0.0-SNAPSHOT</version>

            
            <configuration> <!-- 自定义属性信息 -->
                <version>${project.version}</version>
            </configuration>
        </plugin>
    </plugins>
</build>

命令方式执行

mvn {插件命令前缀}:{mojo的唯一标识(name)},如:

mvn mymaven-plugin-demo:annotationTest

实战

我们来编写一个给某个工程打上一个git tag的demo

编写插件

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.zy</groupId>
    <artifactId>maven-plugin-demo</artifactId>
    <packaging>maven-plugin</packaging>
    <version>1.0.4-SNAPSHOT</version>

    <dependencies>    <!--使用doc的方式-->
        <dependency>
            <groupId>org.apache.maven</groupId>
            <artifactId>maven-plugin-api</artifactId>
            <version>3.6.1</version>
        </dependency>
        <dependency><!--使用注解的方式-->
            <groupId>org.apache.maven.plugin-tools</groupId>
            <artifactId>maven-plugin-annotations</artifactId>
            <version>3.6.1</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-plugin-plugin</artifactId>
                <version>3.6.1</version>            <!-- 插件执行命令前缀 -->
                <configuration>
                    <goalPrefix>git-tag</goalPrefix>
                    <skipErrorNoDescriptorsFound>true</skipErrorNoDescriptorsFound>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

Mojo类

  • AbstractTagMojo: 定义抽象的公共行为与执行动作
public abstract class AbstractTagMojo extends AbstractMojo {

    /**
     * maven工程的版本号
     */
    @Parameter(defaultValue = "${project.version}", required = true, readonly = true)
    protected String version;

    protected Log log = getLog();

    
    public void execute() {
        List<String> commandStr = getCommand();
        commandStr.forEach(this::doExecute);
    }

    /**
     * 不同的指令信息
     * @return
     */
    protected abstract List<String> getCommand();

    /**
     * 具体执行逻辑
     * @param command
     */
    protected void doExecute(String command) {
        try {
            Runtime runtime = Runtime.getRuntime();
            Process process = runtime.exec(command);
            BufferedReader input = new BufferedReader(new InputStreamReader(process.getInputStream()));
            String text = command + "\n";
            log.info(String.format("Command: %s", text));

            String line;
            while ((line = input.readLine()) != null) {
                log.info(String.format("Result: %s", line));
            }
        } catch (IOException e) {
            log.error(e);
        }
    }

    public String getVersion() {
        return version;
    }
}
  • CreateTagMojo: 创建标签
@Mojo(name = "create")
public class CreateTagMojo extends AbstractTagMojo {

    @Override
    protected List<String> getCommand() {
        List<String> commands = new ArrayList<>();
        String version = getVersion();
        commands.add(String.format("git tag %s -m "%s"", version, version));
        return commands;
    }
}
  • DeleteTagMojo: 删除标签
@Mojo(name = "delete")
public class DeleteTagMojo extends AbstractTagMojo {

    @Override
    protected List<String> getCommand() {
        List<String> commands = new ArrayList<>();
        commands.add(String.format("git tag -d %s", getVersion()));
        return commands;
    }

}
  • PushTagMojo: 推送标签到仓库
@Mojo(name = "push")
public class PushTagMojo extends AbstractTagMojo {


    @Override
    protected List<String> getCommand() {
        List<String> commands = new ArrayList<>();
        String version = getVersion();
        commands.add(String.format("git push origin %s", version));
        return commands;
    }
}

使用方

pom.xml

...
<build>
    <plugins>
        <plugin>
            <groupId>com.zy</groupId>
            <artifactId>maven-plugin-demo</artifactId>
            <version>1.0.4-SNAPSHOT</version>
        </plugin>
    </plugins>
</build>
...

命令方式使用

mvn git-tag:create
mvn git-tag:delete
mvn git-tag:push

Idea图形化界面

双击就完事了

image.png

参考资料

maven插件开发文档