java基础

Maven实战-做一个自己的Maven插件

2019-07-25  本文已影响0人  未城居士

前言

写本篇文章主要源于看了一下yapi接口信息采集代码,此工具就是实现了一个maven插件,然后发现自己对如何开发maven插件好像并不是很熟悉,就趁机学习了一下。maven本身主要功能都插件提供的,因此了解maven插件对学习maven也是很有帮助的。本文通过实现一个简单的插件来讲述如果和开发maven插件,比较简单基础。

Maven简单介绍

引用官网的说明:

Apache Maven is a software project management and comprehension tool. Based on the concept of a project object model (POM), Maven can manage a project's build, reporting and documentation from a central piece of information.

官网 https://maven.apache.org/

可以清晰的看到,Apache Maven是一个软件项目管理和理解工具。它基于项目工程对象建模(POM)的概念,能够通过一个中心信息管理项目构建,报告?和文档。简单的理解就是个中心管理项目对象模型的东西。

当然本文的重点是介绍插件构建,首页能够看到

image.png

地址如下

https://maven.apache.org/plugin-developers/index.html

插件简介

Maven大家应该都知道,是一个非常强大的构建工具,生命周期包含项目的:清理,初始化,编译,测试,打包,验证,部署和站点生成等几乎所有的构建步骤,同时,它还是一个依赖管理工具和项目管理工具,帮助我们高效完成这些繁琐的任务,然后大家就可以高高兴兴的写代码了。

而Maven的核心是它的生命周期,但实际上,生命周期又不做任何事情,所有的事情都是交给插件来完成的,每个插件都可以有多个功能,每个功能就是一个插件目标,这种设计思想和模板方法的设计模式比较类似。

例如:我们最常用的命令:mvn clean install,这个命令实际上就使用了maven-clean-plugin和maven-install-plugin插件。目的是清理上一次构建生成的文件并将工程编译打包,安装到maven本地仓库。

开发自己的插件

maven的文档里介绍说,大部分的插件都可以在插件库里面找到,如果实在找不到才需要自己实现一个maven插件,找不到的比例又非常低,据说只有1%(这个具体数字没考证过)

1. pom必要内容

依赖

        <dependency>
            <groupId>org.apache.maven</groupId>
            <artifactId>maven-plugin-api</artifactId>
            <version>3.5.3</version>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>org.apache.maven.plugin-tools</groupId>
            <artifactId>maven-plugin-annotations</artifactId>
            <version>3.6.0</version>
            <scope>provided</scope>
        </dependency>

注意点

image.png

常规的配置这里就不讲, 注意要配置packaging的类型,配置如下:

   <packaging>maven-plugin</packaging>
   <artifactId>hyjal-maven-plugin</artifactId>
   <groupId>com.funnycode.maven.plugin</groupId>
   <version>1.0.0-SNAPSHOT</version>

You will typically name your plugin <yourplugin>-maven-plugin.
Calling it maven-<yourplugin>-plugin (note "Maven" is at the beginning of the plugin name) is strongly discouraged since it's a reserved naming pattern for official Apache Maven plugins maintained by the Apache Maven team with groupId org.apache.maven.plugins. Using this naming pattern is an infringement of the Apache Maven Trademark.

如官方所说,我们插件名字选择<yourplugin>-maven-plugin,即artifactId

2. 创建一个mojo类

什么是Mojo?

A Mojo is really just a goal in Maven, and plug-ins consist of any number of goals (Mojos). Mojos can be defined as annotated Java classes or Beanshell script. A Mojo specifies metadata about a goal: a goal name, which phase of the lifecycle it fits into, and the parameters it is expecting.

https://maven.apache.org/guides/introduction/introduction-to-plugins.html

Mojo我们简单的理解就是个Maven的入口目标,注意能够被定义成带注解的Java类。实际列子如下:

@Mojo(name = "hyjal")
public class HyjalPlugin extends AbstractMojo {

    @Parameter(defaultValue = "${project.groupId}")
    private String groupId;

    @Parameter(defaultValue = "${project.artifactId}")
    private String artifactId;

    @Parameter(defaultValue = "${project.version}")
    private String version;

    @Parameter(defaultValue = "hello")
    private String greeting;

    @Override
    public void execute() throws MojoExecutionException, MojoFailureException {
        StringBuilder sb = new StringBuilder();
        sb.append(greeting)
            .append(":")
            .append("groupId:")
            .append(groupId)
            .append(" artifactId:")
            .append(artifactId)
            .append(" version:")
            .append(version);
        this.getLog().info("========================================");
        this.getLog().info("==============Hyjal Plugin==============");
        this.getLog().info("========================================");

        this.getLog().info(sb.toString());
    }

}

3. 导出插件

在pom增加build的内容,

<build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-plugin-plugin</artifactId>
                <version>3.4</version>
                <configuration>
                    <!-- 如果使用maven2,就一定要加这一行 -->
                    <skipErrorNoDescriptorsFound>true</skipErrorNoDescriptorsFound>
                </configuration>
                <executions>
                    <execution>
                        <id>mojo-descriptor</id>
                        <goals>
                            <goal>descriptor</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.7</source>
                    <target>1.7</target>
                </configuration>
            </plugin>
        </plugins>
    </build>

配置好后,执行mvn clean install就会打到本地仓库

4. 项目引入

在另一个模块的pom中引入

          <plugin>
               <groupId>com.funnycode.maven.plugin</groupId>
               <artifactId>hyjal-maven-plugin</artifactId>
               <version>1.0.0-SNAPSHOT</version>
               <executions>
                   <execution>
                       <phase>compile</phase>
                       <goals>
                           <goal>hyjal</goal>
                       </goals>
                   </execution>
               </executions>
               <configuration>
                   <greeting>welcome</greeting>
               </configuration>
           </plugin>

5. 配置介绍

可以看到上面的<configuration>标签里面有个<greeting>标签,它和代码中的

    @Parameter(defaultValue = "hello")
    private String greeting;

字段名称greeting对应,@Parameter是属性映射的一个注解,defaultValue是hello,如果不配置Mojo对象的此属性就是hello,而例子中我们设置成welcome

配置的内容比较多,可以查看官方说明如下:

http://maven.apache.org/guides/mini/guide-configuring-plugins.html

6. 插件执行命令

mvn groupId:artifactId:version:goal

我们的测试插件就是

mvn com.gongdao.sample:hyjal-maven-plugin:1.0.0-SNAPSHOT:hyjal

效果如下:

[INFO] Scanning for projects...
[INFO]                                                                         
[INFO] ------------------------------------------------------------------------
[INFO] Building sample-all-start 1.0.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO] 
[INFO] --- hyjal-maven-plugin:1.0.0-SNAPSHOT:hyjal (default-cli) @ sample-all-start ---
[INFO] ========================================
[INFO] ==============Hyjal Plugin==============
[INFO] ========================================
[INFO] welcome:groupId:com.funnycode.sample artifactId:sample-all-start version:1.0.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 0.548s
[INFO] Finished at: Thu Jul 25 13:30:31 CST 2019
[INFO] Final Memory: 7M/309M

7. 简化命令

通过上面的操作,我们需要执行的命令如下:

mvn com.gongdao.sample:hyjal-maven-plugin:1.0.0-SNAPSHOT:hyjal

对于冗长的命令我们肯定用的不舒服,maven提供了几种解决方案:

<pluginGroups>
    <pluginGroup>com.funnycode.maven.plugins</pluginGroup>
</pluginGroups>

就可以使用mvn hyjal:hyjal来运行了插件了

8. 插件工程创建

Mojo archetype

mvn archetype:generate \
-DgroupId=sample.plugin \
-DartifactId=hello-maven-plugin \
-DarchetypeGroupId=org.apache.maven.archetypes \
-DarchetypeArtifactId=maven-archetype-plugin

常用插件

大量的插件可以从apache和codehaus获得,还有一些分布在googlecode,sourceforge,github等托管服务中,如Alibaba也有自己的插件库,groupId为:com.alibaba.maven.plugins

结束语

本文只是个简单的入门例子,方便大家的学习。
比如我们看看Mojo的代码有很多属性:

public @interface Mojo {
    String name();

    LifecyclePhase defaultPhase() default LifecyclePhase.NONE;

    ResolutionScope requiresDependencyResolution() default ResolutionScope.NONE;

    ResolutionScope requiresDependencyCollection() default ResolutionScope.NONE;

    InstantiationStrategy instantiationStrategy() default InstantiationStrategy.PER_LOOKUP;

    String executionStrategy() default "once-per-session";

    boolean requiresProject() default true;

    boolean requiresReports() default false;

    boolean aggregator() default false;

    boolean requiresDirectInvocation() default false;

    boolean requiresOnline() default false;

    boolean inheritByDefault() default true;

    String configurator() default "";

    boolean threadSafe() default false;
}

我会在后面的文章中一一解惑。

上一篇下一篇

猜你喜欢

热点阅读