如何构建一个Maven插件

使用Okta的身份管理平台轻松部署您的应用程序 使用Okta的API在几分钟之内即可对任何应用程序中的用户进行身份验证,管理和保护。 今天尝试Okta。

由于其插件生态系统的普及,Apache Maven仍然是Java领域中最流行的构建工具。 很容易找到一个现有的插件来完成您的应用程序所需的几乎所有事情,从确保源文件具有许可证标头到验证版本之间的二进制兼容性。 有时,您需要编写一个自定义插件来满足产品中的要求。

在本教程中,我将向您展示如何构建一个简单的Maven插件来解析项目的当前Git哈希,即git rev-parse --short HEAD

在开始之前,请确保安装Java 8和Apache Maven 。 我使用SDKMAN来安装它们。

如果您想观看视频, 我创建了此博客文章的截屏视频 。

创建一个新的Maven项目

我将使用Maven构建新的Maven插件也就不足为奇了。 您可以使用自己喜欢的IDE来创建一个新项目,但是为了简单起见,我将手动创建一个新的pom.xml文件(在名为example-maven-plugin的新目录中:

<?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.okta.example</groupId><artifactId>example-maven-plugin</artifactId><version>1.0-SNAPSHOT</version><packaging>maven-plugin</packaging><name>Example Maven Plugin</name><description>An Example Maven Plugin</description><properties><maven.compiler.source>1.8</maven.compiler.source><maven.compiler.target>1.8</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding></properties>

这是因为简单,因为它得到,我已经定义了的Maven GAV(G roup ID,A rtifact ID,V版为),名称,以及最重要的是我所设定的packagingmaven-plugin 。 尽管组ID几乎可以是任何东西,但强烈建议使用反向域名表示法,类似于Java包 。

添加Maven依赖项

接下来,我需要定义一些对maven-coremaven-plugin-apimaven-plugin-annotations依赖。 这些都按照provided范围限定,这意味着当插件运行时,使用的实际版本将取决于您安装的Apache Maven的版本。

<dependencies><dependency><!-- plugin interfaces and base classes --><groupId>org.apache.maven</groupId><artifactId>maven-plugin-api</artifactId><version>3.6.0</version><scope>provided</scope></dependency><dependency><!-- needed when injecting the Maven Project into a plugin  --><groupId>org.apache.maven</groupId><artifactId>maven-core</artifactId><version>3.6.0</version><scope>provided</scope></dependency><dependency><!-- annotations used to describe the plugin meta-data --><groupId>org.apache.maven.plugin-tools</groupId><artifactId>maven-plugin-annotations</artifactId><version>3.5</version><scope>provided</scope></dependency></dependencies>

插件构建插件

插件是什么实际上给Maven的它的力量,其核心Maven是只是一个插件框架,所以很自然,我将使用Maven插件来构建一个Maven插件与Maven插件插件 。 乌龟一直向下!

maven-plugin-plugin实际上是自动定义的,因为我使用了上面的maven-plugin的包装类型,要使用较新的版本,我可以在pluginManagment部分中更新插件:

<pluginManagement><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-plugin-plugin</artifactId><version>3.6.0</version></plugin><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-site-plugin</artifactId><version>3.8.2</version></plugin></plugins></pluginManagement>
</project>

我还包括了Maven Site Plugin,它是可选的,在后面的文章中会有更多介绍。

这就对了! 如果您想一次复制并粘贴整个文件,可以从GitHub上获取它。

编写Maven插件代码

在有趣的部分,编写代码! 一个Maven插件实际上是一个或多个“目标”的集合。 每个目标是由一个Java类中定义被称为“魔”(M Aven的平原öLD 的J avaöbject)。

创建一个新类: src/main/java/com/okta/example/maven/GitVersionMojo.java

package com.okta.example.maven;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;
import org.apache.maven.project.MavenProject;/*** An example Maven Mojo that resolves the current project's git revision and adds * that a new {@code exampleVersion} property to the current Maven project.*/
@Mojo(name = "version", defaultPhase = LifecyclePhase.INITIALIZE)
public class GitVersionMojo extends AbstractMojo {public void execute() throws MojoExecutionException, MojoFailureException {// The logic of our plugin will go here}
}

没什么大不了的,现在我有了一个新的Maven插件,它有一个名为version目标。 该项目将在初始化项目时执行。 有几个生命周期可供选择,在本例中,我正在使用“初始化”,因为我希望我的插件在其他插件之前运行。 如果要创建一个插件来创建新文件,则可能需要使用“ generate-resources”阶段。 请查看生命周期参考文档 ,以获取其他阶段的描述。

此时,我可以使用mvn install构建项目,然后使用以下命令执行插件:

# mvn ${groupId}:${artifactId}:${goal}
mvn com.okta.example:example-maven-plugin:version

但是,由于execute方法为空,因此实际上还不会做任何事情。

添加Maven参数

为了使该插件实际起作用,我将添加几个参数。 Maven参数在MOJO类中定义为字段:

/*** The git command used to retrieve the current commit hash.*/
@Parameter(property = "git.command", defaultValue = "git rev-parse --short HEAD")
private String command;@Parameter(property = "project", readonly = true)
private MavenProject project;

值得注意的是,Javadoc对于Maven插件很重要,因为在生成特定于插件的文档时将使用它。 由于我们都是优秀的开发人员,因此我们永远不会忘记添加文档,对吗?

Parameter注释告诉Maven向该字段中注入一个值。 这类似于Spring的Value注释。 对于command字段,我将property值设置为git.command 。 这允许用户使用标准-D表示法在命令行上更改值:

mvn com.okta.example:example-maven-plugin:version \-Dgit.command="git rev-parse --short=4 HEAD"

注入MavenProject以便直接读取或修改项目中的某些内容也是很常见的。 例如, MavenProject使您可以访问依赖项以及pom.xml定义的任何内容。 就我而言,我将添加一个额外的属性,该属性可以在以后的构建中使用。

用Java执行命令

现在我们有了command参数,我们需要执行它! 定义一个新的getVersion方法来处理此逻辑:

public String getVersion(String command) throws MojoExecutionException {try {StringBuilder builder = new StringBuilder();Process process = Runtime.getRuntime().exec(command);Executors.newSingleThreadExecutor().submit(() ->new BufferedReader(new InputStreamReader(process.getInputStream())).lines().forEach(builder::append));int exitCode = process.waitFor();if (exitCode != 0) {throw new MojoExecutionException("Execution of command '" + command + "' failed with exit code: " + exitCode);}// return the outputreturn builder.toString();} catch (IOException | InterruptedException e) {throw new MojoExecutionException("Execution of command '" + command + "' failed", e);}
}

这使用Java的内置Runtime.exec()并捕获输出文本。 任何异常都将作为MojoExecutionException (这将导致生成失败。)

接下来更新execute()方法:

public void execute() throws MojoExecutionException, MojoFailureException {// call the getVersion methodString version = getVersion(command);// define a new property in the Maven Projectproject.getProperties().put("exampleVersion", version);// Maven Plugins have built in logging toogetLog().info("Git hash: " + version);
}

就是这样,现在我们只需要使用插件!

Maven插件的用法

到目前为止,我一直在使用以下命令直接执行插件:

mvn com.okta.example:example-maven-plugin:version

通常,插件会添加到pom.xml因此它们会作为构建的一部分自动运行。 为了说明这一点,我将使用以下pom.xml (在另一个目录中)创建一个新的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.okta.example</groupId><artifactId>example-usage</artifactId><version>1.0-SNAPSHOT</version><packaging>pom</packaging><build><plugins><plugin><groupId>com.okta.example</groupId><artifactId>example-maven-plugin</artifactId><version>1.0-SNAPSHOT</version><configuration><!-- optional, the command parameter can be changed here too --><command>git rev-parse --short=4 HEAD</command></configuration><executions><execution><goals><goal>version</goal></goals></execution></executions></plugin><plugin><groupId>com.github.ekryd.echo-maven-plugin</groupId><artifactId>echo-maven-plugin</artifactId><version>1.2.0</version><inherited>false</inherited><executions><execution><id>end</id><goals><goal>echo</goal></goals><phase>process-resources</phase><configuration><message>${line.separator}${line.separator}The project version is ${project.version}-${exampleVersion}${line.separator}</message></configuration></execution></executions></plugin></plugins></build>
</project>

在该项目结果上运行mvn package将给出输出:

[INFO] Git hash: 1ab3行显示了我的插件执行时,该插件定义的新exampleVersion属性由echo-maven-plugin

注意:将插件添加到pom.xml ,可以使用简写表示法执行该插件: mvn <prefix>:<goal> ,通常,“ prefix”是工件ID减去“ -maven-plugin” 。 例如mvn example:version

Maven插件中的依赖注入

我们的插件很棒,而且很不错,但是所有代码都挤在一个文件中。 我喜欢将代码分解为易于测试的块。 输入Sisu ,将建立Maven容器。 Sisu是一个基于Guice的IoC容器,它是Spring的替代品。

这一切的真正含义是,我可以使用标准的JSR-330( @Inject )注释来破坏我的代码,而不必担心IoC容器的细节!

src/main/java/com/okta/example/maven/VersionProvider.java创建一个新接口:

package com.okta.example.maven;import org.apache.maven.plugin.MojoExecutionException;public interface VersionProvider {String getVersion(String command) throws MojoExecutionException;
}

并将Runtime.exec逻辑从GitVersionMojo到新类src/main/java/com/okta/example/maven/RuntimeExecVersionProvider.java

package com.okta.example.maven;import org.apache.maven.plugin.MojoExecutionException;import javax.inject.Named;
import javax.inject.Singleton;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.concurrent.Executors;@Named
@Singleton
public class RuntimeExecVersionProvider implements VersionProvider {@Overridepublic String getVersion(String command) throws MojoExecutionException {try {StringBuilder builder = new StringBuilder();Process process = Runtime.getRuntime().exec(command);Executors.newSingleThreadExecutor().submit(() ->new BufferedReader(new InputStreamReader(process.getInputStream())).lines().forEach(builder::append));int exitCode = process.waitFor();if (exitCode != 0) {throw new MojoExecutionException("Execution of command '" + command + "' failed with exit code: " + exitCode);}// return the outputreturn builder.toString();} catch (IOException | InterruptedException e) {throw new MojoExecutionException("Execution of command '" + command + "' failed", e);}}
}

我添加了标准Java @Named@Singleton批注,以将该类标记为由IoC容器管理的单例。 这等效于使用Spring的@Component

现在只需更新GitVersionMojo即可注入VersionProvider

@Inject
private VersionProvider versionProvider;public void execute() throws MojoExecutionException, MojoFailureException {String version = versionProvider.getVersion(command);project.getProperties().put("exampleVersion", version);getLog().info("Git hash: " + version);
}

这就对了! 您可以像以前一样构建和运行插件,并获得相同的结果。

一件事,文档!

关于Maven,我最喜欢的事情之一是插件具有一致的文档结构。 要生成文档,请在pom.xml添加一个新的reporting部分:

<reporting><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-plugin-plugin</artifactId><reportSets><reportSet><reports><report>report</report></reports></reportSet></reportSets></plugin></plugins>
</reporting>

您还应该向项目添加更多元数据,但这是可选的。 例如,我将添加组织和前提条件,因为这些条件和前提条件已包含在生成的站点中:

<organization><name>Example, Inc</name><url>https://google.com/search?q=example.com</url>
</organization>
<prerequisites><maven>3.5.0</maven>
</prerequisites>

现在只需运行mvn site即可生成文档! 在浏览器中打开target/site/plugin-info.html 。 明白为什么所有Javadoc都那么重要吗?

1- Maven插件

找到更多

与往常一样,您可以在GitHub上找到本教程的完整源代码。 要了解有关构建插件的更多信息, Apache Maven项目提供了出色的文档。 还可以查看以下其他教程:

  • 使用Okta Maven插件在几秒钟内开始使用Okta
  • Spring Boot登录选项快速指南
  • 使用Hamcrest使Java测试Groovy
  • 许可Maven插件
  • japicmp –一个用于二进制,源代码和semver验证的Maven插件

如果您喜欢本教程,请在Twitter @oktadev上关注我们。 我们还将每周在YouTube频道上发布视频教程。

使用Okta的身份管理平台轻松部署您的应用程序 使用Okta的API在几分钟之内即可对任何应用程序中的用户进行身份验证,管理和保护。 今天尝试Okta。


翻译自: https://www.javacodegeeks.com/2019/11/how-to-build-maven-plugin.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/340994.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

javafx中css选择器_JavaFX技巧12:在CSS中定义图标

javafx中css选择器当您是像我这样来自Swing的UI开发人员时&#xff0c;您很有可能仍在代码中直接设置图像/图标。 最可能是这样的&#xff1a; import javafx.scene.control.Label; import javafx.scene.image.ImageView;public class MyLabel extends Label {public MyLabel(…

python去除图像光照不均匀_CVPR 2020 | 从重建质量到感知质量:用于低光照增强的半监督学习方法...

CVPR 2020 | 从重建质量到感知质量&#xff1a;用于低光照增强的半监督学习方法Code: https://github.com/flyywh/CVPR-2020-Semi-Low-Light1背景本篇为大家介绍我们组被2020年IEEE国际计算机视觉与模式识别会议(CVPR 2020)接收的工作《From Fidelity to Perceptual Quality: A…

多层陶瓷电容器用处_【科普贴】多层陶瓷电容器的制造工序,你知道吗?

本文将向大家介绍多层陶瓷电容器的结构及制造工序。多层陶瓷电容器的基本结构电容器用于储存电荷&#xff0c;其最基本结构如图1所示&#xff0c;在2块电极板中间夹着介电体。图1. 电容器的基本结构电容器的性能指标也取决于能够储存电荷的多少。多层陶瓷电容器为了能够储存更多…

分段式多级离心泵_离心泵与多级离心泵工作原理

离心泵工作原理&#xff1a;离心泵工作时&#xff0c;液体注满泵壳&#xff0c;叶轮高速旋转&#xff0c;液体在离心力作用下产生高速度&#xff0c;高速液体经过逐渐扩大的泵壳通道&#xff0c;动压头转变为静压头。性能特点&#xff1a;高效节能&#xff1a;泵有高效的水力形…

牛客网数据开发题库_数据库刷题—牛客网(21-30)

21.查找所有员工自入职以来的薪水涨幅情况&#xff0c;给出员工编号emp_no以及其对应的薪水涨幅growth&#xff0c;并按照growth进行升序CREATE TABLE employees ( emp_no int(11) NOT NULL, birth_date date NOT NULL, first_name varchar(14) NOT NULL, last_name varchar(16…

弹性堆栈介绍

当您运行对公司至关重要的软件时&#xff0c;您将无法获得仅用于分析一段时间前发生的事情的日志&#xff0c;让客户端告诉您您的应用程序已损坏&#xff0c;而您甚至不知道发生了什么是真实的问题。 解决该问题的方法之一是使用监视和日志记录。 大多数应用程序都将具有日志记…

access统计没有选课的人数_当代大学生发愁求职就业,更发愁“选课”,自主选课变成了负担...

当代大学生除了求职就业&#xff0c;最发愁的就是“选课”。不得不说&#xff0c;随着科技的发展&#xff0c;各行各业都发生了翻天覆地的变化。而在大学里的选课&#xff0c;也因此有了巨大的改变。过去&#xff0c;大学生上课&#xff0c;其实课程都是被安排好的&#xff0c;…

产线数字化软件源码_品质笔记⑥丨卢宇聪:把握数字化趋势,坚定创新发展道路...

6天5夜&#xff0c;跨越3座城市&#xff0c;深度走访7家企业&#xff0c;对话多位企业家……这是一趟开阔视野之旅。我接触了很多之前极少有机会接触的企业&#xff0c;比如做光缆的法尔胜泓晟集团、做节能装备的双良集团、做密封件的天生密封件有限公司等。我以前经常接触的是…

es 安装kopf_Elasticsearch-kopf导览

es 安装kopf当我需要一个插件来显示Elasticsearch的集群状态时&#xff0c;或者需要深入了解通常为经典插件elasticsearch-head所达到的索引时。 由于有很多建议&#xff0c;而且似乎是非官方的继任者&#xff0c;所以我最近更详细地研究了elasticsearch-kopf 。 我喜欢它。 我…

arm 交叉编译找不到so_搭建交叉编译环境并验证

1. 搭建编译环境并验证1.1 实验目的 掌握嵌入式开发环境、交叉编译器的搭建、安装和配置方法 熟悉Linux应用程序的编译、调试方法&#xff0c;能够验证X86平台和ARM平台的差异1.2 实验内容 交叉编译器环境搭建 编写一个典型的Linux应用程序 使用GDB调试Linux程序(PC平台) 用Mak…

雷达的工作原理示意图_电磁阀的构成和工作原理示意图

电磁阀符号的含义&#xff1a;电磁阀符号由方框、箭头、“T”和字符构成。电磁阀图形符号的含义一般如下&#xff1a;1、用方框表示阀的工作位置&#xff0c;每个方块表示电磁阀的一种工作位置&#xff0c;即“位”。有几个方框就表示有几“位”&#xff0c;如二位三通表示有两…

sqlserver拼接字符串换行_1.3【Python】第三章 字符串

人工智能入门与实战第一季&#xff1a;python基础语法字符串是比较常见的数据类型&#xff0c;在第一章中我们最早接触的数据类型就是字符串&#xff1a;"hello world"&#xff0c;字符串可以用单引号’‘或双引号""来表示代码示例&#xff1a;name "…

mot数据集_谈谈ReID与MOT的关系

1.ReID与MOT的联系在MOT任务中&#xff0c;一般常用的特征模型有运动模型和表观模型&#xff0c;其中表观模型以行人重识别(ReID)类算法为主流。Re-ID任务主要解决的是跨摄像头场景下行人的识别与检索&#xff0c;其中存在给定了身份的图片序列query&#xff0c;需要为不同摄像…

jClarity:在Azure上升级到Java

在互联世界公共基础结构的新时代&#xff0c;最大和最重要的两个方面是Java和OpenJDK的诞生和兴起。 因此&#xff0c;许多公司将时间和资源投入到构建最先进的技术上&#xff0c;以确保整个行业在未来几年内在AdoptOpenJDK上拥有丰富的质量&#xff0c;而且免费的OpenJDK二进制…

装饰器模式应用场景_装饰器设计模式的应用

装饰器模式应用场景嗨&#xff0c;您好&#xff01; 今天&#xff0c;我将展示装饰设计模式的实际应用。 装饰器设计模式是一种广泛使用的设计模式&#xff0c;同时在运行期间处理图形&#xff0c;树木和动态更改。 如果您正在寻找或尝试进行递归&#xff0c;这也是一个不错的…

Auto Lisp 标注子样式_CSS 核心样式

CSS核心样式粗细font-weight作用:设置文字是否加粗显示属性名: font-weight, 属于font属性的一个单-属性属性值有两种方式:单词类型、数字类型单词类型数字类型100-900之间的整百数字数字越大&#xff0c;文字显示越粗其中400等价于normal, 700等价于bold字体风格font-style作用…

均质机工作原理动画_3D动画演示:有刷直流电机的工作原理

点上面蓝色字体直观学机械可长期订阅我们法律顾问&#xff1a;赵建英律师下面这张图是电机的分类&#xff0c;在看完这张图后&#xff0c;大家基本也就知道咱们今天说的有刷电机具体属于哪一类了。下面这个是LearnEngineering制作的动画&#xff0c;讲解的是直流电机的工作原理…

a113 智能音箱芯片方案_高通入局智能音箱,首款四核单芯片方案曝光

不得不说&#xff0c;智能音箱已经成为目前重要的科技品类之一&#xff0c;许多公司包括亚马逊、谷歌、苹果、阿里巴巴、小米等等&#xff0c;都在大举进军智能音箱市场。为了尽可能为更多产品提供核心原件&#xff0c;近日&#xff0c;高通公司推出了一款全新的SOC系列——QCS…

隐藏水滴屏的软件_屏下摄像头,实现这一全面屏终极方案有多难?

为了实现真正全面屏&#xff0c;手机厂商们到底能有多拼&#xff1f;在奔向全面屏的征途里&#xff0c;导航键、听筒、传感器、指纹识别模组等都被成功解决&#xff0c;隐藏在边框或屏幕底。唯独前置摄像头&#xff0c;成为全面屏征途的最后一块终极障碍。这场由iPhone X刘海屏…

java ee api_Java EE并发API教程

java ee api这是一个示例章节&#xff0c;摘自Francesco Marchioni编辑的WildFly上的实用Java EE 7开发 。 本章讨论了新的Java EE并发API&#xff08;JSR 236&#xff09; &#xff0c;它概述了使用一组托管资源在Java EE容器上并行执行任务的标准方法。 为了描述如何在您的应…