maven之自定义插件

  Maven 是一个系统管理框架或体系,专注管理构建的生命周期和各个阶段。真正工作的是绑定到各个阶段的 Maven 插件。每个插件具有一个或一个以上的目标,可以将这些插件的目标绑定到 Maven 生命周期的各个阶段中,或直接从命令行运行这些插件的目标。用户可以从 Apache 和其他的参考 Maven 中心仓库获取。当然,这些插件基本上能满足大部分程序员的需求,但是在特殊情况下,可能我们自己有特殊的需求,就要求我们自己去实现一个定制的插件;其实编写插件也并不是很难很复杂的事情,接下来我们开始研究一下,怎么样编写看似高深的、能绑定到 Maven 生命周期的阶段中自动被调用执行的 Maven 插件。

  为了方便大家对编写 Maven 插件的方向和过程有个总体的了解,先介绍一下编写 Maven 插件的基本步骤。

  • 创建 Maven 项目。插件的功能肯定需要编写 Java 类的,所以插件本身就是一个 Maven 项目。当然,相对于以前研究的 Maven 项目,插件项目有它的特殊点:packaging 必须是 maven-plugin 类型,可以通过 maven-archetype-plugin 快速创建一个 Maven 插件项目。
  • 编写插件目标。每个插件都至少包含一个目标,每个目标对应一个独立的 Java 类。这里把这种类叫 Mojo 类(对象)。Mojo 类必须继承 AbstractMojo 父类。
  • 设置目标的配置点。大部分 Maven 件和它的目标都是可以配置的。根据需要,可以在编写 Mojo 的时候给它设置好可以配置的参数。
  • 编写逻辑代码,实现目标功能。用 Java 代码实现插件的功能。
  • 处理错误和日志。当 Mojo 运行的时候发生异常时,需要根据情况控制 Maven 的运行状况,并且用代码实现必要的日志输出,为用户提供必要的提示信息。
  • 测试插件。编写测试案例,绑定(或命令行)执行插件。

自定义插件实现:

  自定义Mojo需要继承 AbstractMojo 这个抽象类,并实现了 execute() 方法,该方法就是用来定义这个 Mojo 具体操作内容,我们只需要根据自己的需要来编写自己的实现即可。那么Maven 如何知道这是一个 Mojo 而不是一个普通的 Java 类呢? Mojo 的查找机制:在处理源码的时候,plugin-tools 会把使用了 @Mojo 注解或 Javadoc 里包含 @goal 注释的类来当作一个 Mojo 类。我们这里使用 @Mojo 注解来进行声明。

1.导入依赖:

<?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.wuzz.demo</groupId>
    <artifactId>wuzz-maven-plugin</artifactId>
    <version>1.0-SNAPSHOT</version>

    <!--打包方式-->
    <packaging>maven-plugin</packaging>
    <dependencies>
        <!--使用doc的方式-->
        <dependency>
            <groupId>org.apache.maven</groupId>
            <artifactId>maven-plugin-api</artifactId>
            <version>3.5.2</version>
        </dependency>
        <dependency><!--使用注解的方式-->
            <groupId>org.apache.maven.plugin-tools</groupId>
            <artifactId>maven-plugin-annotations</artifactId>
            <version>3.5.2</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-plugin-plugin</artifactId>
                <version>3.5.2</version>
                <!-- 插件执行命令前缀 -->
                <configuration>
                    <goalPrefix>wuzz</goalPrefix>
                    <skipErrorNoDescriptorsFound>true</skipErrorNoDescriptorsFound>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
            <!-- 编码和编译和JDK版本 -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

2.Mojo实现类:

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;

/**
 * @description: 类功能描述
 * @author: wuzhenzhao
 * @time 2020/7/15 14:45
 * @since 1.0
 **/
// mojo注解就是maven插件的注解
// 后面配置的是生命周期,我这里配置了PACKAGE,即默认是打包时候执行本插件(这个可以在pom文件指定)
@Mojo(name = "wuzzMojo", defaultPhase = LifecyclePhase.PACKAGE)
public class WuzzMojo extends AbstractMojo {
    // 配置的是本maven插件的配置,在pom使用configration标签进行配置 property就是名字,
    // 在配置里面的标签名字。在调用该插件的时候会看到
    @Parameter(property = "application")
    private String application;

    @Parameter(property = "sourceFolderPath")
    private String sourceFolderPath;

    @Override
    public void execute() throws MojoExecutionException, MojoFailureException {
        System.out.println(
                String.format("Hello World WuzzMojo: 应用名称: %s | 当前应用根目录: %s",
                        application,
                        sourceFolderPath)
        );
    }
}

3. 执行 mvn  install 。成功即可在maven仓库下看到该jar

4.创建一个新的 maven 工程,依赖如下:

<?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.wuzz.demo</groupId>
    <artifactId>maven-plugin-test</artifactId>
    <version>1.0-SNAPSHOT</version>

    <build>
        <plugins>
            <plugin>
                <!--引入刚刚的插件依赖-->
                <groupId>com.wuzz.demo</groupId>
                <artifactId>wuzz-maven-plugin</artifactId>
                <version>1.0-SNAPSHOT</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>wuzzMojo</goal>
                        </goals>
                        <phase>package</phase>
                    </execution>
                </executions>
                <!-- 这里加入的是相关参数,这些参数必须跟插件实现里面的属性保持一致 -->
                <configuration>
                    <application>api</application><!-- 当前应用名称 -->
                    <sourceFolderPath>${basedir}</sourceFolderPath><!-- 当前应用根目录 -->
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

  打开Maven 界面可以看到 :

  双击 wuzzMojo :

   也可以执行  mvn  package 也会执行自定义插件的方法。这里是以pom文件里 phase 定义的值决定,我这里定义成 package,所以只有在打包的时候才会执行。这样就完成了一个简单的  maven 自定义插件

 Mojo 参数:

/**
 * This annotation will mark your class as a Mojo (ie. goal in a Maven plugin).
 *
 * @author Olivier Lamy
 * @since 3.0
 */
@Documented
@Retention( RetentionPolicy.CLASS )
@Target( ElementType.TYPE )
@Inherited
public @interface Mojo
{
    /**
     * goal name (required).唯一必须声明的标注,当用户命令行调用或在pom中配置插件是,需使用该目标名称
     * @return the goal name
     */
    String name();

    /**默认将该目标绑定至default声明周期的某个阶段,这样在配置使用插件目标时,就无需声明phase,如maven-surefire-plugin的test目标带有@phase tes标注
     * default phase to bind your mojo.
     * @return the default phase
     */
    LifecyclePhase defaultPhase() default LifecyclePhase.NONE;

    /**在运行mojo之前必须解析所有指定范围的依赖,如maven-surefire-plugin的test目标带有requiresDependencyResolution test标注,表示执行测试前,所有测试范围的依赖必须得到解析
     * the required dependency resolution scope.
     * @return the required dependency resolution scope
     */
    ResolutionScope requiresDependencyResolution() default ResolutionScope.NONE;

    /**
     * the required dependency collection scope.
     * @return the required dependency collection scope 
     */
    ResolutionScope requiresDependencyCollection() default ResolutionScope.NONE;

    /**
     * your Mojo instantiation strategy. (Only <code>per-lookup</code> and <code>singleton</code> are supported)
     * @return the instantiation strategy
     */
    InstantiationStrategy instantiationStrategy() default InstantiationStrategy.PER_LOOKUP;

    /**
     * execution strategy: <code>once-per-session</code> or <code>always</code>.
     * @return <code>once-per-session</code> or <code>always</code>
     */
    String executionStrategy() default "once-per-session";

    /**该目标是否必须在一个maven项目中运行(如测试插件用于测试其他项目),默认为true。大部分插件目标需依赖一个项目才能运行,但是,maven-help-plugin的system目标例外,它用来显示系统属性和环境变量信息,无需实际项目。
     * does your mojo requires a project to be executed?
     * @return requires a project
     */
    boolean requiresProject() default true;

    /**是否要求项目报告已经生成,默认为false
     * does your mojo requires a reporting context to be executed?
     * @return requires a reporting context
     */
    boolean requiresReports() default false;

    /**当mojo在多模块项目上运行时,该标注表示目标只会在顶层模块运行。
     * if the Mojo uses the Maven project and its child modules.
     * @return uses the Maven project and its child modules
     */
    boolean aggregator() default false;

    /**为true时,该目标就只能通过命令行直接调用。默认为false
     * can this Mojo be invoked directly only?
     * @return invoked directly only
     */
    boolean requiresDirectInvocation() default false;

    /**是否要求maven必须是在线状态,默认值为false
     * does this Mojo need to be online to be executed?
     * @return need to be online
     */
    boolean requiresOnline() default false;

    boolean inheritByDefault() default true;

    /**
     * own configurator class.
     * @return own configurator class
     */
    String configurator() default "";

    /**
     * is your mojo thread safe (since Maven 3.x)?
     * @return is thread safe
     */
    boolean threadSafe() default false;
}

 

posted @ 2020-07-15 19:19  吴振照  阅读(3210)  评论(0编辑  收藏  举报