Maven常用操作:插件的编写和使用

前言

虽然,平时工作基本用不到自定义插件,但手动实现一遍还是很有必要.

这样在配置和调用Maven插件时才能做到知其所以然.

所以本文的标题其实应该是:当我们在使用Maven插件时我们在使用什么.

简单来说,实现自定义插件,只需要继承maven-plugin-api工程中的AbastractMojo并实现无参抽象方法execute即可.

不过这还不够,因为还需要考虑goal,phase和入参等操作.

有两种方式来定义:

1️⃣ JavaDoc方式

2️⃣ 注解方式: 推荐使用.

实战

使用IDEA可以很方便创建Maven插件项目:

在这里插入图片描述

命名项目:maven-plugin-demo;

等待工程生成完成,pom.xml已经引入maven-plugin-api,同时还生成了一个以JavaDoc方式实现的自定义插件示例(详见文末附录),故不再赘述,而是以注解形式实现一个自定义插件,它的作用很简单,只是接收参数并打印.

首先引入包含注解的依赖(别忘了还有maven-plugin-api):

        <dependency>
            <groupId>org.apache.maven.plugin-tools</groupId>
            <artifactId>maven-plugin-annotations</artifactId>
            <version>3.5.2</version>
        </dependency>

继承AbstractMojo:

import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;

@Mojo(name = "hello", defaultPhase = LifecyclePhase.PROCESS_CLASSES)
public class AnnoMojo extends AbstractMojo {
    @Parameter(property = "hello.message", required = true, defaultValue = "${project.name}")
    private String[] message;

    @Override
    public void execute() throws MojoExecutionException, MojoFailureException {
        System.out.println("hello " + String.join("", message) + "~");
    }
}

此时插件已经开发完成.

使用

引入依赖

    <build>
        <plugins>
            <plugin>
                <groupId>org.example</groupId>
                <artifactId>maven-plugin-demo</artifactId>
                <version>1.0-SNAPSHOT</version>
            </plugin>
        </plugins>
    </build>

执行mvn -Dhello.message=world,~~ demo:hello即可实现打印出hello world~~~的效果.

但一般不会这样显式地单独调用,而是靠clean,compiledeployLifecycle来触发,其触发关键点在于插件所附着的phase,它们是有固定的先后顺序的,可以参考官网.

            <plugin>
                <groupId>org.example</groupId>
                <artifactId>maven-plugin-demo</artifactId>
                <version>1.0-SNAPSHOT</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>hello</goal>
                        </goals>
                        <phase>process-sources</phase>
                    </execution>
                </executions>
                <configuration>
                    <message>every body! I'm Ryan</message>
                </configuration>
            </plugin>

此时执行mvn compile就会触发插件的hello目标并打印输出:hello every body! I'm Ryan~.

小结

  1. executions元素可以有多个execution,用来绑定一个phase和多个goal.
  2. configuration元素用来配置插件中定义的parameter

拓展

上节中提到了configuration用来静态配置变量,而命令行可以动态设置,如果同时设置,谁的优先级更高呢?

答案是configuration元素.

同理,pom中定义的phase的优先级高于源码中定义的defaultPhase

总结

  1. 命名规范: maven-plugin-XXX,可以简化命令行调用:mvn XXX:$goal
  2. packaging:maven-plugin
  3. 建议使用注解形式实现,有提示而且排版舒服
  4. 参数包含空格时的,最好使用数组接收
  5. 命令行中的参数不会覆盖pom.xml中已定义的参数
  6. 经常变动的参数不要在configuration中设置.

附录

  1. 默认生成的源码:

    /**
     * Goal which touches a timestamp file.
     *
     * @goal touch
     * @phase process-sources
     */
    public class MyMojo extends AbstractMojo {
        /**
         * Location of the file.
         *
         * @parameter expression="${project.build.directory}"
         * @required
         */
        private File outputDirectory;
    
        public void execute() throws MojoExecutionException {
    		// 此处忽略具体实现
        }
    }
    
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章