maven自定义插件 ---- maven高级篇

maven简介

Maven 作为一个优秀的项目管理工具,其插件机制为其功能扩展提供了非常大的便捷性。虽然说大多数情况下,我们可能不太会自己去编写 Maven 插件,但不排除在某些特殊的情况下,我们需要去完成一个自己的插件,来协助我们处理某些比较通用的事情。正好,最近有一些需求可能需要对 Drools 的一个 Maven 插件进行扩展,所以学习一下 Maven 的插件编写。

Maven 插件的命名规范

一般来说,我们会将自己的插件命名为 -maven-plugin,而不推荐使用 maven–plugin,因为后者是 Maven 团队维护官方插件的保留命名方式,使用这个命名方式会侵犯 Apache Maven 商标。

什么是 Mojo?

Mojo 就是 Maven plain Old Java Object。每一个 Mojo 就是 Maven 中的一个执行目标(executable goal),而插件则是对单个或多个相关的 Mojo 做统一分发。一个 Mojo 包含一个简单的 Java 类。插件中多个类似 Mojo 的通用之处可以使用抽象父类来封装。

创建 Mojo 工程

这里,我们使用 Idea 作为开发工具进行讲解,创建工程选择 Maven,然后在模板中找到 maven-archetype-mojo(其实也可以不用选择任何模板,直接下一步),点击下一步,输入对应的参数,如:com.sm/hello-maven-plugin/0.0.1,最后点击完成即可创建一个简单的 Mojo 工程。

配置pom.xml

创建完成后,工程内会生成对应的 pom.xml 文件。其内容比较简单,与普通 Maven 工程的 pom.xml 基本一致,只是自动添加了对 maven-plugin-api 的依赖,这个依赖里面会包含一些 Mojo 的接口与抽象类,在后续编写具体的 Mojo 时再进行详细讲解。

<!-- maven插件api接口 -->
<dependency>
    <groupId>org.apache.maven</groupId>
    <artifactId>maven-plugin-api</artifactId>
    <version>2.0</version>
</dependency>
<!-- maven注解 -->
<dependency>
    <groupId>org.apache.maven.plugin-tools</groupId>
    <artifactId>maven-plugin-annotations</artifactId>
    <version>3.1</version>
</dependency>

与普通 pom.xml 文件一个重要的不同之处是它的打包方式:

<packaging>maven-plugin</packaging>
简单 Mojo 的创建

工程创建完毕后,我们开始 Mojo 创建之旅,上面提到过 Mojo 是一个简单的 Java 类,那我们创建第一个 Mojo 类用于打印一行输出。

import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
/**
 * @goal hello
 */
public class HelloMojo extends AbstractMojo {

    public void execute() throws MojoExecutionException, MojoFailureException {
        System.out.println("hello world");
    }

}

观察一下这个类,我们发现它继承了 AbstractMojo 这个抽象类,并实现了 execute() 方法,该方法就是用来定义这个 Mojo 具体操作内容,我们只需要根据自己的需要来编写自己的实现即可。

Mojo 操作的实现我们了解了,那怎么让 Maven 知道这是一个 Mojo 而不是一个普通的 Java 类呢?这里,就需要说一下 Mojo 的查找机制了,在处理源码的时候,plugin-tools 会把使用了 @Mojo 注解或 Javadoc 里包含 @goal 注释的类来当作一个 Mojo 类。在上面的例子中,我们使用了 Javadoc 的方法来声明一个 Mojo。同样我们也可以使用 @Mojo 注解来进行声明:

@Mojo(name = "hello")
public class HelloMojo extends AbstractMojo {

    public void execute() throws MojoExecutionException, MojoFailureException {
        System.out.println("hello world");
    }
}
运行自定义 Plugin

与使用其它插件类似,我们需要在 pom.xml 文件中引入插件。正常情况应该是先将编写的maven插件上传到nexus私服,然后再配置,这样就会从nexus私服上下载
nexus私服 教程请参考:

1. nexus的linux安装包: https://download.csdn.net/download/miracle_8/12056904
2. 安装: https://blog.csdn.net/BuFanQi_Info/article/details/81317844
3. 上传jar:  https://blog.csdn.net/u013887008/article/details/79429973
4. 删除jar: https://blog.csdn.net/u013958151/article/details/80311462

当然考虑到maven的加载机制是先从本地的repository加载的,可以直接在本地repository按照maven的目录配置对应的数据目录并上传自定义插件包即可

之后就可以在本地的项目中添加自定义插件的引用了

<build>
    <plugins>
        <plugin>
            <groupId>com.sm</groupId>
            <artifactId>hello-maven-plugin</artifactId>
            <version>0.0.1</version>
        </plugin>
    </plugins>
</build>
验证

先执行命令:

mvn install

然后执行:

mvn com.sm:hello-maven-plugin:0.0.1:hello

即可看到输出:

[INFO] Scanning for projects...
[INFO]                                                                         
[INFO] ------------------------------------------------------------------------
[INFO] Building hello-maven-plugin Maven Mojo 0.0.1
[INFO] ------------------------------------------------------------------------
[INFO] 
[INFO] --- hello-maven-plugin:0.0.1:hello (default-cli) @ hello-maven-plugin ---
hello world
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 0.249 s
[INFO] Finished at: 2017-03-26T12:59:47+08:00
[INFO] Final Memory: 6M/123M
[INFO] ------------------------------------------------------------------------

缩短执行命令
在刚才运行插件的时候,我们使用全量的插件指引,但这个实在是太长太繁琐了,那我们是否可以缩短我们的执行命令呢?答案肯定是可以的,如果你想要执行的是你本地库中最新版本的插件,那么你可以删除掉版本号;如果你的命名满足前面提及的两种命令方式,你可以直接使用插件名及 goal 名来运行对应的插件,如:

mvn sm:hello

你会得到与之前完全一样的结果。

绑定 Maven 执行周期

你还可以将插件配置为将特定目标,从而附加到构建生命周期中的某个特定阶段。如:

<build>
    <plugins>
        <plugin>
            <groupId>com.sm</groupId>
            <artifactId>hello-maven-plugin</artifactId>
            <version>0.0.1</version>
            <executions>
                <execution>
                    <goals>
                        <goal>hello</goal>
                    </goals>
                    <phase>package</phase>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

继承AbstractMojo 的类中,参数可以通过命令赋值,例如:

/**
 *
 * @goal echo
 * @phase process-sources
 */
public class Hello extends AbstractMojo {

    /**
     * @parameter property="echo.message" default-value="Hello World..."
     */
     //@Parameter(defaultValue="${project}", readonly=true)
    private String message;

    public void execute() throws MojoExecutionException, MojoFailureException {
        System.out.println("hello world");

        getLog().info("hello mymojo : "+message);
    }

}

其中注释就是maven插件很重要的元数据

/**
 * @goal CustomMavenMojo:表示该插件的服务目标
 * @phase compile:表示该插件的生效周期阶段
 * @requiresProject false:表示是否依托于一个项目才能运行该插件
 * @parameter expression="${name}":表示插件参数,使用插件的时候会用得到 express在最新的maven中已经被替代了
 * @required:代表该参数不能省略
 */

执行:

mvn com.sm:hello-maven-plugin:0.0.1:hello -Decho.message="Fuck shit "

(MyMojo类中的message 参数的javadoc注释是 echo.message, 通过命令赋值时,需要传入
-Decho.message=XXX 这种形式 )

完整代码及验证命令如下
项目结构

在这里插入图片描述

项目代码
// hello-maven-plugin:pom.xml
<?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">
    <parent>
        <artifactId>1ScalaStudy</artifactId>
        <groupId>org.example</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.sm</groupId>
    <artifactId>hello-maven-plugin</artifactId>
    <packaging>maven-plugin</packaging>


    <dependencies>
        <!-- maven插件api接口 -->
        <dependency>
            <groupId>org.apache.maven</groupId>
            <artifactId>maven-plugin-api</artifactId>
            <version>2.0</version>
        </dependency>
        <!-- maven注解 -->
        <dependency>
            <groupId>org.apache.maven.plugin-tools</groupId>
            <artifactId>maven-plugin-annotations</artifactId>
            <version>3.1</version>
        </dependency>
        <!--<dependency>-->
            <!--<groupId>org.apache.maven.plugins</groupId>-->
            <!--<artifactId>maven-site-plugin</artifactId>-->
            <!--<version>3.6</version>-->
        <!--</dependency>-->

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>2.5.1</version>
                <configuration>
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-plugin-plugin</artifactId>
                <version>3.2</version>
                <configuration>
                    <skipErrorNoDescriptorsFound>true</skipErrorNoDescriptorsFound>
                </configuration>
            </plugin>
        </plugins>
    </build>
    <!--<reporting>-->
        <!--<plugins>-->
            <!--<plugin>-->
                <!--<groupId>org.apache.maven.plugins</groupId>-->
                <!--<artifactId>maven-javadoc-plugin</artifactId>-->
                <!--<version>3.2.0</version>-->
            <!--</plugin>-->
            <!--<plugin>-->
                <!--<groupId>org.apache.maven.plugins</groupId>-->
                <!--<artifactId>maven-project-info-reports-plugin</artifactId>-->
                <!--<version>3.1.0</version>-->
            <!--</plugin>-->
        <!--</plugins>-->
    <!--</reporting>-->

</project>

// hello-maven-plugin:AbstractHelloMojo.java
package com.sm;

import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;

public abstract class AbstractHelloMojo extends AbstractMojo {


    @Override
    public void execute() throws MojoExecutionException, MojoFailureException {
        System.out.println("AbstractHelloMojo");
    }
}

// hello-maven-plugin:HelloMojo.java
package com.sm;

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.COMPILE)
public class HelloMojo extends AbstractHelloMojo {

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

    @Override
    public void execute() throws MojoExecutionException, MojoFailureException {
        System.out.println("HelloMojo:" + msg);
    }
}

//  hello-maven-plugin:HiMojo.java
package com.sm;

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;

import java.util.List;

@Mojo(name = "hi", defaultPhase = LifecyclePhase.COMPILE)
// defaultPhase: 表示默认的执行阶段, 在引入插件并配置好executions的goal之后, 程序会首先根据
// defaultPhase来执行, 也可以通过显示的配置<phase>来改变执行的阶段
// defaultPhase和<phase>必须配置其中一个, 否则无法执行
public class HiMojo extends AbstractHelloMojo {

    @Parameter
    private List<String> options;

    @Override
    public void execute() throws MojoExecutionException, MojoFailureException {
        System.out.println("HiMojo:" + options);
    }
}

// 插件使用: maven-plugin-test:pom.xml
<?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">
    <parent>
        <artifactId>1ScalaStudy</artifactId>
        <groupId>org.example</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.sn</groupId>
    <artifactId>maven-plugin-test</artifactId>

    <build>
        <plugins>
            <plugin>
                <groupId>com.sm</groupId>
                <artifactId>hello-maven-plugin</artifactId>
                <version>1.0-SNAPSHOT</version>
                <!-- 默认的goal里面的参数配置, 可以被execution里面的配置覆盖 -->
                <!--<configuration>-->
                    <!--<options>-->
                        <!--<option>1</option>-->
                        <!--<option>2</option>-->
                    <!--</options>-->
                    <!--<msg>1</msg>-->
                <!--</configuration>-->
                <executions>
                    <execution>
                        <id>hello1</id>
                        <phase>clean</phase>
                        <configuration>
                            <msg>hahaha</msg>
                        </configuration>
                        <goals>
                            <goal>hello</goal>
                        </goals>
                    </execution>
                    <execution>
                        <id>hello2</id>
                        <!-- 采用默认的phase -->
                        <!--<phase>compile</phase>-->
                        <configuration>
                            <msg>hahaha2</msg>
                        </configuration>
                        <goals>
                            <goal>hello</goal>
                        </goals>
                    </execution>
                    <execution>
                        <!--<phase>clean</phase>-->
                        <id>hi</id>
                        <goals>
                            <goal>hi</goal>
                        </goals>
                        <configuration>
                            <options>
                                <option>1</option>
                                <option>2</option>
                            </options>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>2.3.2</version>
                <configuration>
                    <source>1.7</source>
                    <target>1.7</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

源码附件: https://download.csdn.net/download/miracle_8/12901610

验证命令总结
maven常用命令:
名词: lifecycle phase goal => lifecycle包含多个phase, phase包含多个goal, 
mvn [一个或多个phase|一个或多个goal], 多个phase|goal可以混合, maven按照顺序执行
a. 内置的lifecycle:default, clean and site. The default lifecycle handles your project deployment, the clean lifecycle handles project cleaning, while the site lifecycle handles the creation of your project's site documentation.

1. 安装到本地仓库: maven clean install
2. 部署到远程仓库: maven clean deploy

3. 查看插件拥有的goals: 
mvn help:describe -Dplugin=groupId:artifactId:version
例子: mvn help:describe -Dplugin=com.sm:hello-maven-plugin:1.0-SNAPSHOT

4. 单独执行插件的某个goal:
mvn groupId:artifactId:goal
例子: mvn com.sm:hello-maven-plugin:hello

5. 简化执行插件的某个goal: (参数最好设置的长一点, 比如下面的 msg改为test.test.msg)
mvn globalPrefix:goal -Dparam=value
例子: mvn hello:hello -Dmsg=123

6. 执行插件中指定的execution:
mvn globalPrefix:goal@executionID =>  maven版本必须是3.3.1以上
例子: mvn hello:hello@hello1

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值