【Maven】maven 插件开发实战

附上我历时三个月总结的 Java 面试 + Java 后端技术学习指南,这是本人这几年及春招的总结,目前,已经拿到了大厂offer,拿去不谢!

下载方式

1. 首先扫描下方二维码

2. 后台回复「Java面试」即可获取

前言

众所周知,maven 实质上是一个插件执行框架,所有的工作都是通过插件完成的。包括我们日常使用到的类似 install、clean、deploy、compiler。。。这些命令,其实底层都是一个一个的 maven 插件。

如何开发自己的插件

1. maven 插件的命名规范

在写一个项目之前,第一件事就是确定一个名称。maven 插件也不例外。它有着自己的一套命名规范。但是规范很简单,一句话就可以概括,**官方插件命名的格式为 maven-xxx-plugin,非官方的插件命名为 xxx-maven-plugin 。**是不是觉得很眼熟,没错,spring boot starter 的命名也有类似的规范。

好的,我们的第一个 maven 插件项目就叫 demo-maven-plugin 吧。

2. 创建项目

名称起好了,下一步就是创建这个项目。如果你使用 idea 的话,那么创建十分的便捷,按如下步骤即可:

2.1 选择 org.apache.maven.archetypes:maven-archetype-mojo 为骨架创建项目

  1. 选择创建新项目

  2. 选择通过 maven 创建

  3. 勾选 Create from archetype 通过项目骨架创建

  4. 选择 org.apache.maven.archetypes:maven-archetype-mojo

  5. 点击下一步

2.2 输入在第一步起的项目名

点击 Next

2.3 点击 Finish 完成项目创建

2.4  分析项目文件

项目结构

可以看到生成的项目就是我们最最常见的 maven 项目的结构,生成的文件也很少,一个 pom.xml 文件,一个 MyMojo 文件,简单介绍一下这两个文件

pom.xml
<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/maven-v4_0_0.xsd"><modelVersion>4.0.0</modelVersion><groupId>cn.coder4j.study.example</groupId><artifactId>demo-maven-plugin</artifactId><packaging>maven-plugin</packaging><version>1.0-SNAPSHOT</version><name>demo-mavne-plugin Maven Mojo</name><url>http://maven.apache.org</url><dependencies><dependency><groupId>org.apache.maven</groupId><artifactId>maven-plugin-api</artifactId><version>2.0</version></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>3.8.1</version><scope>test</scope></dependency></dependencies>
</project>

首先生成的项目 pom.xml 中,自动依赖了两个项目,一个是 maven-plugin-api ,这个是开发 maven 插件必须依赖的核心包。另一个是单元测试时使用的 junit 包。这两个没什么要注意的,真正要注意的是这个项目的 packaging,通常我遇到的 packaging 都是 jar、war、pom,这里比较特殊是 maven-plugin。

MyMojo.java
package cn.coder4j.study.example;/** Copyright 2001-2005 The Apache Software Foundation.** Licensed under the Apache License, Version 2.0 (the "License");* you may not use this file except in compliance with the License.* You may obtain a copy of the License at**      http://www.apache.org/licenses/LICENSE-2.0** Unless required by applicable law or agreed to in writing, software* distributed under the License is distributed on an "AS IS" BASIS,* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.* See the License for the specific language governing permissions and* limitations under the License.*/import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;import java.io.File;
import java.io.FileWriter;
import java.io.IOException;/*** Goal which touches a timestamp file.** @goal touch** @phase process-sources*/
public class MyMojoextends AbstractMojo
{/*** Location of the file.* @parameter expression="${project.build.directory}"* @required*/private File outputDirectory;public void execute()throws MojoExecutionException{File f = outputDirectory;if ( !f.exists() ){f.mkdirs();}File touch = new File( f, "touch.txt" );FileWriter w = null;try{w = new FileWriter( touch );w.write( "touch.txt" );}catch ( IOException e ){throw new MojoExecutionException( "Error creating file " + touch, e );}finally{if ( w != null ){try{w.close();}catch ( IOException e ){// ignore}}}}
}

首先生成的类继承了 AbstractMojo 这个抽象类,这里是 maven 插件的规范要求,maven 插件必须要继承 AbstractMojo 并实现他的 execute 方法。

另外可以看到类与方法使用了很多 tag。注意是 tag 而不是注解,注解是直接标记的,而 tag 是在文档注释里面的。

其中 @goal 这个 tag 的作用是指定插件的命名,比如我们常用的 mvn clean,这个 clean 就是他的 @goal 。

而 @phase 是绑定插件执行的生成周期,比如你绑定在 clean 这个周期,那你在执行 clean 的时候会自动触发你的插件。

@parameter 用来指定插件的参数。

小朋友你是否有很多问号?tag 这个东西写在文档注释里面的东西,方便是方便但是容易写错呀,写错没有语法报错,写对时候也没有语法提示,为什么不直接用注解的形式呢?原因是 java 的注解是 jdk1.5 之后才有的,而实现 maven 的时候还没有这种语法。所以要一条路走到黑,一直背这个历史包袱吗?当然不是,后面我们会说解决办法。另外,这种写法虽然不推荐使用了,但是有些 maven 的经典插件由于完成时间比较早,熟悉这些 tag 对于理解代码也有帮助。

3. 开发插件

3.1 代码未动,依赖先行 pom.xml

<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/maven-v4_0_0.xsd"><modelVersion>4.0.0</modelVersion><groupId>cn.coder4j.study.example</groupId><artifactId>demo-maven-plugin</artifactId><packaging>maven-plugin</packaging><version>1.0-SNAPSHOT</version><name>demo-mavne-plugin Maven Mojo</name><url>http://maven.apache.org</url><dependencies><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></plugin></plugins></build>
</project>

相较于默认的 pom.xml 文件,我们做了如下几个变动:

  1. 升级 maven-plugin-api 的插件版本到 3.5.2 。原生的 2.0 实在是太老了。

  2. 添加 maven-plugin-annotations 这个依赖,还记得上面说的 tag 的事吗?有了这个依赖就可以直接使用注解了

  3. 添加 maven-plugin-plugin 插件依赖,添加这个依赖主要是为了在 jdk1.8 能编译通过,否则会报错

3.2 DemoMojo.java

/***  * **  *  * blog.coder4j.cn*  *  * Copyright (C) 2016-2020 All Rights Reserved.*  ***/
package cn.coder4j.study.example;import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;/*** @author buhao* @version DemoMojo.java, v 0.1 2020-03-30 22:51 buhao*/
@Mojo(name = "hello")
public class DemoMojo extends AbstractMojo {@Parameter(name = "name", defaultValue = "kiwi")private String name;public void execute() throws MojoExecutionException, MojoFailureException {getLog().info("hello " + name);}
}

首先,同生成的类一样,我们的类必须继承 AbstractMojo 并实现他的 execute 方法,而 execute 方法其实就是这个插件的入口类。

示例代码中有两个很重要的注解,一个是 @Mojo ,它主要用来定义插件相关的信息相当于上面说的 @goal ,其中 name 属性用来指定这个插件名称,同 clean 类似。

另外一个重要注解 @Parameter ,则是用来指定插件运行时使用的参数,其中 name 是参数名,defaultValue 顾名思义是默认值,也就是在用户没有设置的时候使用的值。

详细的插件及作用如下:

import org.apache.maven.execution.MavenSession;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecution;
import org.apache.maven.plugin.descriptor.PluginDescriptor;
import org.apache.maven.plugins.annotations.Component;
import org.apache.maven.plugins.annotations.Execute;
import org.apache.maven.plugins.annotations.InstantiationStrategy;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.plugins.annotations.ResolutionScope;
import org.apache.maven.project.MavenProject;
import org.apache.maven.settings.Settings;// 此Mojo对应的目标的名称
@Mojo( name = "<goal-name>",aggregator = <false|true>,configurator = "<role hint>",// 执行策略executionStrategy = "<once-per-session|always>",inheritByDefault = <true|false>,// 实例化策略instantiationStrategy = InstantiationStrategy.<strategy>,// 如果用户没有在POM中明确设置此Mojo绑定到的phase,那么绑定一个MojoExecution到那个phasedefaultPhase = LifecyclePhase.<phase>,requiresDependencyResolution = ResolutionScope.<scope>,requiresDependencyCollection = ResolutionScope.<scope>,// 提示此Mojo需要被直接调用(而非绑定到生命周期阶段)requiresDirectInvocation = <false|true>,// 提示此Mojo不能在离线模式下运行requiresOnline = <false|true>,// 提示此Mojo必须在一个Maven项目内运行requiresProject = <true|false>,// 提示此Mojo是否线程安全,线程安全的Mojo支持在并行构建中被并发的调用threadSafe = <false|true> ) // (since Maven 3.0)// 何时执行此Mojo
@Execute( goal = "<goal-name>",           // 如果提供goal,则隔离执行此Mojophase = LifecyclePhase.<phase>, // 在此生命周期阶段自动执行此Mojolifecycle = "<lifecycle-id>" )  // 在此生命周期中执行此Mojo
public class MyMojoextends AbstractMojo
{@Parameter( name = "parameter",// 在POM中可使用别名来配置参数alias = "myAlias",property = "a.property",defaultValue = "an expression, possibly with ${variables}",readonly = <false|true>,required = <false|true> )private String parameter;@Component( role = MyComponentExtension.class,hint = "..." )private MyComponent component;@Parameter( defaultValue = "${session}", readonly = true )private MavenSession session;@Parameter( defaultValue = "${project}", readonly = true )private MavenProject project;@Parameter( defaultValue = "${mojoExecution}", readonly = true )private MojoExecution mojo;@Parameter( defaultValue = "${plugin}", readonly = true )private PluginDescriptor plugin;@Parameter( defaultValue = "${settings}", readonly = true )private Settings settings;@Parameter( defaultValue = "${project.basedir}", readonly = true )private File basedir;@Parameter( defaultValue = "${project.build.directory}", readonly = true )private File target;public void execute(){}
}

回到示例上了,我们这个插件作用很简单,根据配置输出 hello xxx,如果没有配置就输出 hello kiwi。我们在写插件时,当然不会这样写,但是通过这个 demo,你就掌握了 maven 插件的大部分知识,可以自己做一些很有趣的插件。

4. 使用插件

首先上面我们的代码写完了,必须要 Install 一下,否则别的项目无法直接依赖,如果你还想给其它人使用,那还需上传到 maven 仓库。

4.1 依赖插件

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

在我们想使用插件的项目中,添加如上配置,其中 plugin 中使用我们插件的  GAV 信息。

4.2 启动插件

如果上面配置的都正确,那么在 idea 右侧的 Maven 中,你配置的项目的 Plugins 下会多了一个 demo(具体根据你插件项目的名称),而 demo 里面会有一个 demo:hello,其中这个 demo 对应你插件项目的名称,而 hello 对应你插件的名称也就是 @Mojo 中的 name 。

好的,我们双击一下,demo:hello ,会输出如下日志:

这样,我们的第一个 Maven 插件就好了。

4.3 配置参数

可能你还记得,我们在写 DemoMojo 的时候还指定了一个 name 属性,并且为它指定了一个 Parameter,这个如何使用。只要在依赖的插件下面添加 configuration 标签就可以了。

    <build><plugins><plugin><groupId>cn.coder4j.study.example</groupId><artifactId>demo-maven-plugin</artifactId><version>1.0-SNAPSHOT</version><configuration><name>tom</name></configuration></plugin></plugins></build>

其中 configuration 标签内的标签,对应你定义的参数名称,而且 idea 还有语法提示,很 nice。

好的,我们再运行一下,结果如下:

好的,大功告成。

其它

参考链接

Maven 插件开发[1]

Maven 插件编写[2]

项目源码

因为篇幅有限,无法贴完所有代码,如遇到问题可到 github[3] 上查看源码。

最后,再附上我历时三个月总结的 Java 面试 + Java 后端技术学习指南,这是本人这几年及春招的总结,目前,已经拿到了大厂offer,拿去不谢!

下载方式

1. 首先扫描下方二维码

2. 后台回复「Java面试」即可获取

Reference

[1]

Maven 插件开发: https://blog.gmem.cc/maven-plugin-development

[2]

Maven 插件编写: https://www.cnblogs.com/sniffs/p/11985699.html

[3]

github: https://github.com/kiwiflydream/study-example/tree/master/demo-maven-plugin

【Maven】maven 插件开发实战相关推荐

  1. 架构师工具箱(二)Maven——Maven生成Archetype

    写在前面: 你好,欢迎关注! 我热爱技术,热爱分享,热爱生活, 我始终相信:技术是开源的,知识是共享的! 博客里面的内容大部分均为原创,是自己日常的学习记录和总结,便于自己在后面的时间里回顾,当然也是 ...

  2. Maven——Maven概述

    Maven概述 Maven是意第绪语,意为知识的积累,最初是为了简化Jakarta Turbine项目中的构建过程.有几个项目,每个项目都有自己的Ant构建文件,所有项目都略有不同.JAR已检入CVS ...

  3. Maven: maven parent.relativepath point at wrong local pom

    Maven: maven parent.relativepath point at wrong local pom 参考:https://blog.csdn.net/qwfys200/article/ ...

  4. Maven——Maven核心概念——史上最烂系列

    Maven 是目前最流行的自动化构建工具,对于生产环境下多框架.多模块整合开发有重要作用.Maven 是一款在大型项目开发过程中不可或缺的重要工具.(自己粗略写了一个SSM项目之后,回顾头来看这个,会 ...

  5. maven 自定义插件开发

    创建maven工程 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www ...

  6. Maven——maven中的 pom和import的作用到底是什么

    1.前言 在微服务的项目中,我们是不是经常在父项目中写一些统一版本的jar包,但是其中很多时候都有如下类似代码的影子,对于下面的代码中pom和type的作用是否明白呢,如果不明白,欢迎看下面的内容. ...

  7. [maven]maven插件 tomcat7-maven-plugin 的使用

    使用 tomcat7-maven-plugin,可以将tomcat内嵌到web项目中,直接运行webapp项目. 第一步.pom.xml的配置: <build><plugins> ...

  8. maven 打包指定依赖包_[Maven]-Maven基础-01-基础概念

    Maven基础 1.基础概念 Maven基础概念 什么是Maven 什么是理想的项目构建? 高度自动化,跨平台,可重用的组件,标准化的 什么是依赖?为什么要进行依赖管理? 自动下载,统一依赖管理 有哪 ...

  9. CloudIDE插件开发实战:教你如何调试代码

    摘要:今天我们来重点介绍下CloudIDE插件的调试技巧,在插件开发过程中调试作为重要的问题分析和定位手段能够有效帮助开发者提升插件质量. 今天文章中的样例工程我们继续以上一篇<实战CloudI ...

最新文章

  1. php short_open_tag asp_tags
  2. mysql 5.6 mysqldump 简单_mysqldump的简单用法及其原理
  3. 全球及中国制糖行业销售规模与运营态势研究报告2022版
  4. Windows中常用的git GUI客户端的介绍
  5. 转换string_类型转换详解
  6. html:(13):ol-li和div作用
  7. 标识符的命名规定java 0126
  8. 职业生涯中的选择时机非常重要,各种条件还没成熟时的时候,因为诱惑而贸然行事,只会得到适得其反的结果...
  9. Ping记录时间的方法
  10. Java数据库操作要点
  11. PPT做的很好却不会讲?掌握这些职场PPT演讲技巧,不再惧怕做汇报
  12. 安装AdventureWorks2008R2示例数据库
  13. 小谈 Ubuntu 联网
  14. calloc()函数
  15. UnsatisfiedDependencyException: Error creating bean with name XXXController'
  16. 误杀进程致电脑白屏解决办法
  17. MATLAB学习笔记 函数记录(三)
  18. 电脑安装了git之后拉取代码报错:git fatal: Authentication failed for
  19. CSS3 帧动画(Sprite,直译叫雪碧图)
  20. matlab小作业答案,MATLAB编程作业答案.doc

热门文章

  1. C#+uploadify3.1上传示例,可使用中文按钮
  2. jflash合并stm32f103之bin文件及hex文件
  3. IAR编译的工程无法正常仿真的问题
  4. tessorflow实战
  5. cmake (0)简介
  6. MIMIC 以太坊医疗项目开发(6)Web3智能合约API
  7. 进程间通信(3) 剪贴板
  8. 创新实训个人记录:P versus NP
  9. buu Dangerous RSA
  10. DVWA学习(一)SQL Injection