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

前言

写本篇文章主要源于看了一下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)的概念,能够通过一个中心信息管理项目构建,报告?和文档。简单的理解就是个中心管理项目对象模型的东西。

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

Maven实战-做一个自己的Maven插件_第1张图片
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必要内容

依赖

        
            org.apache.maven
            maven-plugin-api
            3.5.3
            provided
        

        
            org.apache.maven.plugin-tools
            maven-plugin-annotations
            3.6.0
            provided
        

注意点

Maven实战-做一个自己的Maven插件_第2张图片
image.png

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

   maven-plugin
   hyjal-maven-plugin
   com.funnycode.maven.plugin
   1.0.0-SNAPSHOT

You will typically name your plugin -maven-plugin.
Calling it maven--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.

如官方所说,我们插件名字选择-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());
    }

}
  • The class org.apache.maven.plugin.AbstractMojo provides most of the infrastructure required to implement a mojo except for the execute method.
  • The annotation "@Mojo" is required and control how and when the mojo is executed.
  • The execute method can throw two exceptions:
    • org.apache.maven.plugin.MojoExecutionException if an unexpected problem occurs. Throwing this exception causes a "BUILD ERROR" message to be displayed.
    • org.apache.maven.plugin.MojoFailureException if an expected problem (such as a compilation failure) occurs. Throwing this exception causes a "BUILD FAILURE" message to be displayed.
  • 还有个log的这边不做说明

3. 导出插件

在pom增加build的内容,


        
            
                org.apache.maven.plugins
                maven-plugin-plugin
                3.4
                
                    
                    true
                
                
                    
                        mojo-descriptor
                        
                            descriptor
                        
                    
                
            

            
                org.apache.maven.plugins
                maven-compiler-plugin
                
                    1.7
                    1.7
                
            
        
    

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

4. 项目引入

在另一个模块的pom中引入

          
               com.funnycode.maven.plugin
               hyjal-maven-plugin
               1.0.0-SNAPSHOT
               
                   
                       compile
                       
                           hyjal
                       
                   
               
               
                   welcome
               
           

5. 配置介绍

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

    @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提供了几种解决方案:

  • mvn com.alibaba.maven.plugins.test:maven-gav-plugin:gav,去掉版本后,会调用本地仓库的最新版本
  • maven解析插件仓库元数据时会先找默认的groupId,默认的有:org.apache.maven.plugins和org.codehaus.mojo两个,其次找到对应的artifactId,然后结合当前groupId和最新的版本来确定坐标,即可以将自己的groupId改为:org.apache.maven.plugins或org.codehaus.mojo
  • 通过配置settings.xml文件让maven检查其他的groupId上的插件仓库元数据,即在settings文件中添加如下配置:

    com.funnycode.maven.plugins

就可以使用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;
}

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

你可能感兴趣的:(Maven实战-做一个自己的Maven插件)