我的Dojo中有一个Mojo(如何编写Maven插件)

我一直忙于在工作中使用Maven的腋窝。 对于很多开发人员,我会听到:“那又怎样。” 不同之处在于,我通常在无法直接访问Internet的环境中工作。 因此,当我说我经常使用Maven时,这意味着某些事情。

依赖地狱

公平地说,我在示例中一直在随意使用Maven。 我发现下载依赖项并避免“依赖关系地狱”更为方便。 我必须为正在使用的库下载库的情况。 例如,必须下载Hamcrest才能使用JUnit。 在家里,放入对JUnit的依赖关系,而Maven为我下载Hamcrest,因为它是JUnit的依赖关系。 如果存在Hamcrest的依赖关系,Maven也会下载该依赖关系。 在工作时,我需要研究JUnit具有哪些依赖关系,然后研究这些依赖关系具有哪些依赖关系。 由于这种情况,我避免使用库。

形势变化

更改是因为我在工作中使用Spring Roo。 Roo使用Maven来管理它需要合并的Spring依赖项。 由于此更改,我在开发网络上设置了Nexus服务器,并开始了将依赖项从Internet转移到开发网络的过程。 这使我了解了Maven。

我对Maven的了解

在阅读了《 Maven入门》和《 Maven Build Customization》两本书之后,我对Maven以及如何创建本文的主题有了一个很好的了解。 我可以继续学习我所学到的东西,但是我将继续专注于学习Maven插件所需的知识。 我确实假设一个人看到了一个pom文件并从现在开始运行了一些Maven构建。 如果还没有,请购买我读过的书,或者先去http://maven.apache.org 。

Maven插件丰富

Maven基于插件架构。 在Maven中执行任何操作的都是插件。 从诸如编译之类的核心功能到创建网站。 可以想象,每个插件都有某些共同点。

Maven是面向包,生命周期,阶段和目标的

Maven以将某种内容构建到某种打包项目(例如jar文件)中而闻名。 显而易见,这是pom文件的第一行。 可能不知道的是,有一系列“阶段”或“生命周期”恰巧完成了构建程序包的过程(请参阅我在其中所做的事情)。 实际上,这些阶段之一被称为“打包”。 生命周期中的默认阶段列表如下:

  1. 验证
  2. 产生源
  3. 过程源
  4. 产生资源
  5. 流程资源
  6. 编译
  7. 过程类
  8. 生成测试源
  9. 流程测试源
  10. 生成测试资源
  11. 流程测试资源
  12. 测试编译
  13. 过程测试类
  14. 测试
  15. 准备包装
  16. 整合前测试
  17. 整合测试
  18. 整合后测试
  19. 校验
  20. 安装
  21. 部署

Maven构建中正在进行很多工作! 所有这些都由某种插件运行。 每个插件都是由可以设置为在生命周期的特定阶段运行的目标组成的。 例如,将maven-jar-plugin的jar目标设置为在打包阶段运行。

制作插件

现在,您已经对构建过程进行了更深入的了解,是时候解释创建Maven插件所需的内容了。

插件充满了Mojos

什么是魔力? Mojo是Maven普通的Old Java Objects的缩写。 它是Maven识别的插件的最小单位。 所有插件均由mojos制成。 每个mojo与一个目标相关联。 因此,要使一个插件具有多个目标,就需要多个mojo。 令人遗憾的是,我将显示的示例只有一个mojo,但是该示例还将显示测试插件的最佳实践。

最佳做法是唯一允许的做法

看看我在标题中与Dojo交易相关的工作吗? 如果有兴趣,编写插件涉及命名约定,单元测试和集成测试。 命名约定是最重要的

  1. 您不会破坏Apache商标
  2. 其他人知道一个人做了一个插件。

名称中有什么?

Apache插件的命名约定为maven- <title> -plugin。 例如,jar插件名为maven-jar-plugin。 对于其他所有人,命名约定为<title> -maven-plugin。 例如,我创建的示例名为hinter-maven-plugin。 发表本文时使用的另一个示例是Spring Boot的插件,它名为spring-boot-maven-plugin。 Spring Boot的源代码在这里 。 我分叉了它,所以我可以细读和滥用代码。 我的叉子可以在这里找到。 如果您想一起滥用它,请在完成您特定的滥用行为后,将我的副本分叉并发送给我请求请求。 无论如何,如果使用Apache的命名约定,那就是商标侵权。 你被警告了。

单元测试

自动化的单元和集成测试也很重要。 单元测试所遵循的目录模式与普通单元测试略有不同,因此请耐心等待。

对插件进行单元测试时的目录结构为

unit_test_plugin

请注意,所有测试目录都组织在测试目录下。 一个正在制作的是将使用该插件的项目的一个小版本。 测试资源目录下是一个单元目录,后跟子目录中单元的名称。 目标是一次测试一个Mojo。 由于我的示例只有一个mojo,因此我仅设置了一个测试。 除了目录设置以外,还有其他区别,但示例部分将进行介绍。

整合测试

我发现该测试将使您最大程度地了解一个人的特定插件及其工作方式。 目的是测试某种情况,就像它是实际项目构建的一部分一样。 当我指的是实际项目构建时,我的意思是甚至有一个仅用于集成构建的临时存储库。 在阅读了有关如何设置测试的信息之后,我大量借鉴了spring-boot-maven-plugin的集成测试设置和mini pom文件。 好的,我将一些文件复制到示例代码中。 只是通知一个人Spring Boot做得对。 只是为了安全起见,克隆是只读的,或者为了安全起见请分叉其代码。 目录结构如下所示。

it_test_plugin

集成测试不在test目录下,而是位于it目录下src目录下。 我本可以进行更多的集成测试,但到目前为止已经足够了。

该示例插件的灵感来自于我心不在and,需要提醒我所做的一切。 我曾想创建一个洗狗提醒插件,但是我决定使用一个普通的提醒插件,因为这样我就可以用它提醒我需要做的任何事情。

Pom文件

<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>com.darylmathison</groupId><artifactId>reminder-maven-plugin</artifactId><packaging>maven-plugin</packaging><version>1.0-SNAPSHOT</version><name>reminder-maven-plugin Maven Mojo</name><url>http://maven.apache.org</url><properties><mavenVersion>3.2.1</mavenVersion><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><maven.compiler.source>1.8</maven.compiler.source><maven.compiler.target>1.8</maven.compiler.target></properties><dependencies><!-- Maven dependencies --><dependency><groupId>org.apache.maven</groupId><artifactId>maven-plugin-api</artifactId><version>${mavenVersion}</version></dependency><dependency><groupId>org.apache.maven</groupId><artifactId>maven-core</artifactId><version>${mavenVersion}</version></dependency><dependency><groupId>org.apache.maven.plugin-tools</groupId><artifactId>maven-plugin-annotations</artifactId><version>3.2</version><scope>provided</scope></dependency><dependency><groupId>org.apache.maven</groupId><artifactId>maven-compat</artifactId><version>3.2.1</version><scope>test</scope></dependency><dependency><groupId>org.apache.maven.plugin-testing</groupId><artifactId>maven-plugin-testing-harness</artifactId><version>3.1.0</version><scope>test</scope></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>3.8.1</version><scope>test</scope></dependency></dependencies><build><pluginManagement><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><configuration><source>1.8</source><target>1.8</target></configuration></plugin><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-plugin-plugin</artifactId><version>3.2</version><executions><execution><id>mojo-descriptor</id><goals><goal>descriptor</goal></goals></execution></executions><configuration><skipErrorNoDescriptorsFound>true</skipErrorNoDescriptorsFound></configuration></plugin></plugins></pluginManagement></build><profiles><profile><id>run-its</id><build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-invoker-plugin</artifactId><version>1.7</version><configuration><debug>true</debug><cloneProjectsTo>${project.build.directory}/it</cloneProjectsTo><cloneClean>true</cloneClean><pomIncludes><pomInclude>*/pom.xml</pomInclude></pomIncludes><addTestClassPath>true</addTestClassPath><postBuildHookScript>verify</postBuildHookScript><localRepositoryPath>${project.build.directory}/local-repo</localRepositoryPath><settingsFile>src/it/settings.xml</settingsFile><goals><goal>clean</goal><goal>compile</goal><goal>package</goal></goals></configuration><executions><execution><id>integration-test</id><goals><goal>install</goal><goal>run</goal></goals></execution></executions></plugin></plugins></build></profile></profiles>
</project>

可以看到,构建一个插件需要很多插件和依赖项。 这里有一个注释依赖项。 这是Junit的版本。 该版本必须为3.8.1。 这是因为Maven扩展了TestCase类,以使其更易于进行单元测试。 很快就会看到。 注意两个插件,一个是maven-plugin-plugin,另一个是maven-invoker-plugin。 maven-plugin-plugin可以自动为插件创建帮助目标。 maven-invoker-plugin用于集成测试。 它的功能是运行Maven项目,如果一个人正在测试pom中运行它就很方便。

提醒Mojo.java

package com.darylmathison;import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;@Mojo(name = "remind",defaultPhase = LifecyclePhase.PACKAGE,requiresOnline = false, requiresProject = true,threadSafe = false)
public class ReminderMojo extends AbstractMojo {@Parameter(property = "basedir", required = true)protected File basedir;@Parameter(property = "message", required = true)protected String message;@Parameter(property = "numOfWeeks", defaultValue = "6", required = true)protected int numOfWeeks;public void execute() throws MojoExecutionException {File timestampFile = new File(basedir, "timestamp.txt");getLog().debug("basedir is " + basedir.getName());if(!timestampFile.exists()) {basedir.mkdirs();getLog().info(message);timestamp(timestampFile);} else {LocalDateTime date = readTimestamp(timestampFile);date.plus(numOfWeeks, ChronoUnit.WEEKS);if(date.isBefore(LocalDateTime.now())) {getLog().info(message);timestamp(timestampFile);}}}private void timestamp(File file) throws MojoExecutionException {try(FileWriter w = new FileWriter(file)) {LocalDateTime localDateTime = LocalDateTime.now();w.write(localDateTime.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));} catch (IOException e) {throw new MojoExecutionException("Error creating file " + file, e);}}private LocalDateTime readTimestamp(File file) throws MojoExecutionException {try(FileReader r = new FileReader(file)) {char[] buffer = new char[1024];int len = r.read(buffer);LocalDateTime date = LocalDateTime.parse(String.valueOf(buffer, 0, len));return date;} catch(IOException ioe) {throw new MojoExecutionException("Error reading file " + file, ioe);}}
}

这是插件中唯一的Mojo,并且可以找到,它非常简单,但是显示了Mojo api提供的一些很酷的功能。 类注释定义目标的名称为“ remind”,并且它不是线程安全的。 它还定义了默认阶段为打包阶段。 我要提到的最后一件事是任何成员变量都可以成为参数。 这成为目标插件的参数。

提醒MojoTest

package com.darylmathison;import org.apache.maven.plugin.testing.AbstractMojoTestCase;import java.io.File;/*** Created by Daryl on 3/31/2015.*/
public class ReminderMojoTest extends AbstractMojoTestCase {@Overrideprotected void setUp() throws Exception {super.setUp();}@Overrideprotected void tearDown() throws Exception {super.tearDown();}public void testJustMessage() throws Exception {File pom = getTestFile("src/test/resources/unit/reminder-mojo/pom.xml");assertNotNull(pom);assertTrue(pom.exists());ReminderMojo myMojo = (ReminderMojo) lookupMojo("remind", pom);assertNotNull(myMojo);myMojo.execute();}
}

这是mojo的基本单元测试用例。 测试类扩展AbstractMojoTestCase以获得诸如getTestFile和lookupMojo之类的功能。 以下是测试pom文件。

单元测试Pom文件

<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>com.darylmathison.test</groupId><artifactId>reminder-maven-plugin-test-reminder</artifactId><packaging>jar</packaging><version>1.0-SNAPSHOT</version><name>reminder-maven-plugin Maven Mojo</name><dependencies><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>3.8.1</version><scope>test</scope></dependency></dependencies><build><plugins><plugin><groupId>com.darylmathison</groupId><artifactId>reminder-maven-plugin</artifactId><version>1.0-SNAPSHOT</version><configuration><basedir>target/test-classes/unit/reminder-mojo</basedir><message>Wash the doggies</message></configuration></plugin></plugins></build>
</project>

只是定义插件的主pom文件的迷你版本。

整合测试

这是值得的,因为它实际上是Maven项目中的一个单独的Maven项目。 本练习的主要重点是查看插件将执行的操作,而不是其他操作。 示例应用程序很简单,就可以在其中构建Maven项目。 要注意的另一件事是,pom文件使用一些过滤来匹配groupId,artifactId和主插件pom的版本。

Pom文件

<?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.darylmathison.it</groupId><artifactId>new-timestamp</artifactId><version>0.0.1.BUILD-SNAPSHOT</version><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties><build><plugins><plugin><groupId>@project.groupId@</groupId><artifactId>@project.artifactId@</artifactId><version>@project.version@</version><executions><execution><id>blah</id><goals><goal>remind</goal></goals></execution></executions><configuration><message>Wash the doggies</message></configuration></plugin></plugins></build>
</project>

SampleApp

package java.test;/*** Created by Daryl on 4/5/2015.*/
public class SampleApp {public static void Main(String[] args) {System.out.println("out");}
}

验证

System.out.println(basedir);
def file = new File(basedir, "timestamp.txt");
return file.exists();

验证脚本是为了确保插件能够完成其预期的工作。 它只是检查timestamp.txt文件是否存在,因为该插件在找不到时间戳文件时会创建一个。 Maven检查验证脚本的输出是对还是错。

结论

哇! 我在这篇文章中介绍了很多内容。 我去举了一个如何创建一个Maven插件的例子。 我还展示了如何使用最佳实践来测试该插件。 我得到了两本书之间的信息,以及一个正在进行的开源项目的实例。 示例代码在GitHub上托管这里 。 这代表了我的新示例主页中的第一个示例。

参考文献

    • 介绍Maven
    • Maven构建定制
    • http://maven.apache.org
    • Spring靴

翻译自: https://www.javacodegeeks.com/2015/04/there-is-a-mojo-in-my-dojo-how-to-write-a-maven-plugin.html

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

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

相关文章

在linux下安装mongo数据库,Linux系统下安装MongoDB

MongoDB提供了Linux系统上32位和64位的安装包&#xff0c;你可以在官网下载安装包。下载完安装包&#xff0c;并解压 tgz(以下演示的是 64 位 Linux上的安装) 。curl-O https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-3.0.6.tgz # 下载tar-zxvf mongodb-linux-x86_64-…

Windows 8.1 新增控件之 Hyperlink

Windows 8.1 新增控件之 Hyperlink 原文:Windows 8.1 新增控件之 HyperlinkHyperlink 控件应该不用过多介绍大家肯定十分清楚其作用&#xff0c;它的功能就像HTML中的<a href””>标签一样&#xff0c;只不过是在XAML中实现。 使用Hyperlink 标记的文字在应用中会以特殊颜…

Linux的slab和nginx的区别,Nginx核心知识100讲》nginx Slab管理器

极客专栏《Nginx核心知识100讲》38小节的笔记nginx 不同的worker之间需要共享信息的时候&#xff0c;只能通过共享内存。共享内存会使用链表&#xff0c;红黑树这样的数据结构。但是每个红黑树上有很多节点&#xff0c;每个节点上都需要分配内存去存放。怎样把一整块共享内存切…

睡觉时:新增的Java 8新增功能

自Java 8推出以来&#xff0c;最有趣的功能是什么&#xff1f; Java 8最近庆祝了它的第一个生日&#xff0c;而主要版本刚刚一年多前发布。 这当然值得庆祝。 自从最初的Java 8版本问世以来&#xff0c;已经发布了六个更新。 这些更新中的一些元素是次要的&#xff0c;但是如…

树莓派安装win10arm linux,在树莓派3B 上安装 Windows 10 ARM 版的方法

早先关注我们的朋友可能对《国外开发者尝试在树莓派3上运行Windows 10桌面版》有印象。本文转自 amatfan.com&#xff0c;文末视频来自 daveb778(感谢柠栀和刺分享)&#xff0c;给出了如何在树莓派3B上安装Windows10 ARM版&#xff0c;是的&#xff0c;这次并非IoT版&#xff0…

各种触摸手势

轻按(UITapGestureRecognizer) -- 用一个或多个手指在屏幕上轻按。 按住(UILongPressGestureRecognizer) -- 用一个或多个手指在屏幕上按住。 轻扫(UISwipeGestureRecognizer) -- 用一个或多个手指沿特定方向轻扫。 张合(UIPinchGestureRecognizer) -- 张合手指以缩放对象。 旋…

宝塔linux取消登录,宝塔面板如何关闭安全入口

通过 SSH 终端关闭安全入口通过 SSH 终端连接rm -f /www/server/panel/data/admin_path.pl即可关闭宝塔 Linux 面板的安全入口&#xff0c;关闭之后的面板登录地址就是&#xff1a;http://服务器 IP:8888。不过关闭这个安全入口之后很难恢复&#xff0c;所以不建议关闭宝塔面板…

[ofbiz]设置任务计划(job),提示service_item已经传递

问题描述&#xff1a;设置任务计划(job)&#xff0c;提示service_item已经传递 解决办法&#xff1a; 红色框内不要填写&#xff0c;就可以了。"已经传递"是翻译的不准确&#xff0c;应该是"已过时"&#xff0c;所以不设置开始时间&#xff0c;或者开始时间…

c支限界算法语言n皇后问题分,n皇后问题(分析)

这道题需要用到回溯算法&#xff0c;现在在这里先简单的介绍一下这个算法&#xff1a;回溯算法也叫试探法&#xff0c;它是一种系统地搜索问题的解的方法。回溯算法的基本思想是&#xff1a;从一条路往前走&#xff0c;能进则进&#xff0c;不能进则退回来&#xff0c;换一条路…

android系统相机自动录像,android 调用系统相机录像并保存

1、在AndroidManifest.xml中添加如下代码tools:ignore"ProtectedPermissions" />android:authorities"${applicationId}.provider"android:name"android.support.v4.content.FileProvider"android:exported"false"android:grantUri…

【原创】jpgraph中文乱码问题的解决

php jpgraph库非常强大&#xff0c;可以在后台生成图片 后台生成在需要导出图表型报告的时候非常有用&#xff0c;当然&#xff0c;前端的可视化还是要用highcharts/echarts/anycharts等类库 比较麻烦的是中文乱码问题&#xff0c;有3个地方乱码&#xff1a; legendsetStickLab…

getstring方法android,JSON中optString和getString方法的区别

JSON中optString和getString方法的区别更新时间&#xff1a;2017年07月07日 15:18:24 投稿&#xff1a;mrroptString方法会在对应的key中的值不存在的时候返回一个空字符串&#xff0c;但是getString会抛一个JSONException 。下面通过一段代码给大家介绍JSON中optString和get…

jpanel把原本内容覆盖掉_A5:APP关键词覆盖你该了解哪些

A5:APP关键词覆盖你该了解哪些点击上方蓝字关注我们苹果ios/安卓-各大应用商店ASO优化大全IOS关键词覆盖1、苹果AppStore关键词搜索的权重排序为app标题、副标题>app关键词>app描述>宣传文本及评论(App关键词100字符)。2、如何优化100字符关键词①、根据产品用户画像分…

android音乐播放器音乐加载,Android开源音乐播放器之在线音乐列表自动加载更多...

系列文章前言当咱们的ListView数据比较多时&#xff0c;咱们通常都会选择分页显示&#xff0c;而分页显示就须要一个动做触发加载更多操做&#xff0c;一般咱们会使用上拉加载更多&#xff0c;但我以为不够人性化&#xff0c;由于用户须要手动上拉&#xff0c;因此更加人性化的…

最短路径--Floyd算法

Floyd算法 1.定义概览 Floyd-Warshall算法&#xff08;Floyd-Warshall algorithm&#xff09;是解决任意两点间的最短路径的一种算法&#xff0c;可以正确处理有向图或负权的最短路径问题&#xff0c;同时也被用于计算有向图的传递闭包。Floyd-Warshall算法的时间复杂度为O(N3)…

vue 打开一个iframe_Vue 之五 —— 单元测试

单元测试&#xff08;unit testing&#xff09;&#xff1a;是指对软件中的最小可测试单元进行检查和验证。代码的终极目标有两个&#xff0c;第一个是实现需求&#xff0c;第二个是提高代码质量和可维护性。单元测试是为了提高代码质量和可维护性&#xff0c;是实现代码的第二…

Hibernate如何存储二级缓存条目

介绍 使用数据库访问抽象层的好处是可以透明地实现缓存&#xff0c;而不会泄漏到业务逻辑代码中 。 Hibernate Persistence Context充当事务后写式高速缓存 &#xff0c;将实体状态转换转换为DML语句。 持久性上下文充当逻辑事务存储&#xff0c;并且每个Entity实例最多可以具…

file协议访问linux,Mozilla Firefox for Android 'file'协议未授权访问漏洞(CVE-2014-1501)

发布日期&#xff1a;2014-03-18更新日期&#xff1a;2014-04-02受影响系统&#xff1a;Mozilla Firefox < 28.0描述&#xff1a;--------------------------------------------------------------------------------BUGTRAQ ID: 66424CVE(CAN) ID: CVE-2014-1501Firefox是…

dcdc芯片效率不高的原因_半导体厂商如何做芯片的出厂测试?

本文来源于知乎&#xff0c;已获作者授权&#xff0c;谢谢。作者&#xff1a;温戈链接&#xff1a;https://www.zhihu.com/question/20584576/answer/1538640891知乎网友提问&#xff1a;半导体厂商如何做芯片的出厂测试&#xff1f;例如 Intel 的 CPU、手机处理器&#xff0c;…

魅族android n内测报名,不再万年Android 5.0! Flyme安卓N内测招募开启

科客点评&#xff1a;恰逢Flyme五周年庆&#xff0c;这算的是给煤油们最大的礼物。近日&#xff0c;魅族Flyme系统非常活跃&#xff0c;为国内友商操碎了心&#xff0c;为此适配了一众友商热门机型&#xff0c;刷了不少存在感&#xff0c;但这显然不是魅族要搞的“大事情”。6月…