前言

今年的更新频率简直是降至冰点了,一方面平时加班相对多一些了,下班只想玩手机;另一方面,好像进了大厂后,学习动力也很低了,总之就,很懒散,博客的话,今年都才只更新了不到5篇。

现在慢慢有一点状态,开始学点技术;今天这篇就是讲maven插件,为啥会折腾这个,公司内有个mybatis generator,针对公司内部做了一些定制开发,具体内容不知道,但是,有个很蛋疼的问题,在根据数据库表,反向生成po的时候,不能把数据库表的字段的注释,给生成为po的field 注释。

之前试过自己折腾一下,解决这个问题,但是实在不了解maven插件这块,因此一直就忍了将就用,大不了就没有注释嘛;前几个月就把maven源码下载下来了,但是源码里一堆的单元测试,却一直不知道怎么像我们平时使用的方式那样去debug,最后就三天打鱼两天晒网地瞎看,效果很差,看了多少就忘多少,最近才把debug插件的方式折腾ok,这里就分享给大家。

下边正文。

越是复杂的开源项目,里面用到的maven插件就越多,一个pom,大几百行是常事,经常呢,大家都是只知道怎么配置,或者说,不知道怎么配置,需要改配置的时候,就一顿猛搜,经常网上搜出来的,可能还因为版本不匹配发生“他文章里可以,我这边为啥不行”。

反正,总结一句话,maven插件很多时候,对大家来说,就是一个黑盒。

而我们恰恰不太能忍受黑盒,当然了,像什么jvm那种c++写的黑盒就算了,让人头秃。

另外,可以再给大家一个看这篇文章的理由,就问你一个问题:spring boot是怎么打包成fat jar,又是怎么从一个fat jar启动的?

是吧,这里的答案就在spring boot的maven插件里了。今天我们肯定不会那么复杂,搞个clean插件学习下,就ok了。

怎么单行调试一个插件的源码呢

创建演示工程

我们需要一个maven的project,最终弄完,我这边样子是这样的:

下边是步骤:直接像下面这样生成一个,然后next结束:

为了方便演示,我们pom.xml里,删除了元素里的内容(主要是被插件版本的管理,我们为了演示,直接删了,用默认版本就行),删除后的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>org.example</groupId>
<artifactId>test-project</artifactId>
<version>1.0-SNAPSHOT</version> <name>test-project</name>
<!-- FIXME change it to the project's website -->
<url>http://www.example.com</url> <properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>
</properties> <dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies> <build>
</build>
</project>

大家看上面这个pom,很干净,会不会以为这样就没有配置插件了呢,不是的,默认的,就会给我们的maven的生命周期绑定一些插件,比如在clean阶段绑定maven-clean-plugin插件。可以看我下图,可以看到这里还是有好几个插件的,为了力求简单好理解,我们关注clean插件,我这边是2.5版本,大家对于版本号不用纠结,可能不同的idea版本出来的会有差异。

调试clean插件

怎么调试呢,首先得触发maven的clean插件执行,是吧?怎么触发执行呢?

如何触发执行clean插件

针对这种命令很简单的,不需要给插件传参数的命令,直接上图这样就可以触发调试运行。

大家来看看执行效果:

上面这一串,看起来很长,其实很多都是-D指定的SystemProperty和classpath,最终呢,其实就是java -main类 -args的格式。

这里的参数就是"clean:clean"。

去哪里打断点

有人开始问了,你不是说调试吗,这都一把跑完了啊,再说了,我想打断点去哪里打呢?

ok,要打断点,我们得知道,mvn clean肯定会执行到的那个方法,然后才能在那里提前打断点埋伏,就好像我们总是知道,程序执行,会进入main方法一样。

而mvn clean,一定会执行到clean插件中的CleanMojo这个class(这部分知识算是需要提前了解的部分):

要调试这个类,必须得在当前的project(idea里,一个project包含多个module)里,能找到这个class。在idea里,老子上来就是double shift,

看起来,找不到这个类啊,还怎么玩?最简单的办法是,先直接把这个jar包加到project里面,

添加到libraries里:

加的时候,会提示你,要不要加入到当前这个project,要选:yes。加了后,就可以看到:

老子抬手又是doubel shift,可以看到,这个cleanMojo已经存在了。

既然存在了,接下来就是打断点:

继续触发执行debug

可以看到,已经成功停在了我们的断点上,接下来单步调试就行。但是哈,大家也注意到,我们这边因为是打在反编译的class上的,而反编译的class呢,肯定没有源码那么舒服的,这个问题呢,也简单,等我循序渐进来讲。

去哪里打断点--方式2

我们下边这个方式,当然是想办法在源码上打断点,源码去哪里获取?

https://mvnrepository.com/artifact/org.apache.maven.plugins/maven-clean-plugin/2.5

源码下载下来后,我尝试了下图这样的方式(就是在前面方案的基础上,把源码附上了):

这种方式,打个断点,看看:

这个方式是可以调试插件本身那几个java文件,但是插件依赖的那些,就还是有问题,这种方式吧,鸡肋。

去哪里打断点--最推荐的方式

我们还是不搞那些有的没的了,来官方的插件开发地址拉代码:

https://maven.apache.org/scm.html

下载后解压,发现是个maven工程,舒服了。直接导入idea。导入后,我们打好了断点,下边开始,跑一波debug。

可以看到,这把舒服了,确确实实,调试的是源代码了。但是,这里提醒一下,不要想着去改代码,如果直接改,改了肯定就class和java源码的行号,对应不上了,至于为什么,这是一个值得大书特书的故事了,留待后续。

扩展

前面我们说的,触发maven clean执行,是用的这种方式。

实际上,这种只能应付简单场景,不需要传参什么的,复杂场景还是需要像下面这样:

比如,我们公司的那个mybatis 生成器:

就会指定很多参数,比如对应的配置文件的位置,对吧。

【曹工杂谈】详解Maven插件调试方法的更多相关文章

  1. maven插件调试方法

    前言 以IntelliJ IDEA为例,通常我们调试maven项目时,都是直接点击调试按钮即可.但maven编写的插件就不同了,由于插件需要打包成Jar加载到项目中,所以如果我们需要在编写插件源码时调 ...

  2. 【曹工杂谈】说说Maven框架和插件的契约

    说说Maven框架和插件的契约 前言 Maven框架就像现在公司内的各种平台方,规定一些契约,然后想办法拉动业务方,一起在这个平台上去做生态共建.Maven也是这样,其实它就是一个插件执行的框架,Ma ...

  3. 【曹工杂谈】Maven源码调试工程搭建

    Maven源码调试工程搭建 思路 我们前面的文章<[曹工杂谈]Maven和Tomcat能有啥联系呢,都穿打补丁的衣服吗>分析了Maven大体的执行阶段,主要包括三个阶段: 启动类阶段,负责 ...

  4. 【曹工杂谈】Mysql-Connector-Java时区问题的一点理解--写入数据库的时间总是晚13小时问题

    背景 去年写了一篇"[曹工杂谈]Mysql客户端上,时间为啥和本地差了整整13个小时,就离谱",结果最近还真就用上了. 不是我用上,是组内一位同事,他也是这样:有个服务往数据库in ...

  5. [转]javascript console 函数详解 js开发调试的利器

    javascript console 函数详解 js开发调试的利器   分步阅读 Console 是用于显示 JS和 DOM 对象信息的单独窗口.并且向 JS 中注入1个 console 对象,使用该 ...

  6. 详解Grunt插件之LiveReload实现页面自动刷新(两种方案)

    http://www.jb51.net/article/70415.htm    含Grunt系列教程 这篇文章主要通过两种方案详解Grunt插件之LiveReload实现页面自动刷新,需要的朋友可以 ...

  7. 详解jquery插件中(function ( $, window, document, undefined )的作用。

    1.(function(window,undefined){})(window); Q:(function(window,undefined){})(window);中为什么要将window和unde ...

  8. 详解Python模块导入方法

    python常被昵称为胶水语言,它能很轻松的把用其他语言制作的各种模块(尤其是C/C++)轻松联结在一起.python包含子目录中的模块方法比较简单,关键是能够在sys.path里面找到通向模块文件的 ...

  9. 【曹工杂谈】Maven和Tomcat能有啥联系呢,都穿打补丁的衣服吗

    Maven和Tomcat能有啥联系呢,都穿打补丁的衣服吗 前奏 我们上篇文章,跟大家说了下,怎么调试maven插件的代码,注意,是插件的代码.插件,是要让主框架来执行的,主框架是谁呢,就是maven ...

随机推荐

  1. raven靶机

    仅供个人娱乐 靶机信息 Raven 下载地址:https://www.vulnhub.com/entry/raven-1,256/ 一.主机探测 端口信息 目录扫描 80端口 根据页面开始搜寻有用的信 ...

  2. Java 反射(二)运行时获取类的信息

    目录 一.获得类的运行时结构 1. 获得类的名字 2. 获得类的属性 获取属性列表 获取指定属性 3. 获取类的方法 获得类的方法列表 获得指定方法 4. 获得的构造器 获得构造器列表 获得指定构造器 ...

  3. 记客户端出现Connect reset问题排查。

    客户访问我们地址出现Connect reset. 网上查询说是服务端关闭,客户端还在读,就会出现Connect reset. 我们就排查为什么服务端会关闭. 网络的同事说收到了客户端的信息,但是被服务 ...

  4. Java中使用split方法根据英文问号?切割字符串时报错

    因为正则表达式的原因,我们无法在java中直接使用String.split("?"),需要先转义其正确写法为: public static void splitStr() { St ...

  5. CentOS8 安装MySQL5.7

    CentOS_8 安装MySQL5.7 1.在安装之前,如果你的系统曾经安装过Mariadb,请先卸载:yum remove mariadb*2.安装依赖 yum install -y epel-re ...

  6. NOIP 模拟 $20\; \rm y$

    题解 \(by\;zj\varphi\) 首先发现一共最多只有 \(2^d\) 种道路,那么可以状压,(不要 \(dfs\),会搜索过多无用的状态) 那么设 \(f_{i,j,k}\) 为走 \(i\ ...

  7. NOIP 模拟 9 分组

    题解 这道题我们发现可以根据 \(k=1\) 和 \(k=2\) 的情况分别讨论 \(k=1\) 时,我们发现要保证字典序,那么我们从后往前扫,扫的时候判断一下当前数是否会和上一段的冲突. 复杂度瓶颈 ...

  8. 题解 P3317 [SDOI2014]重建

    题解 前置芝士:深度理解的矩阵树定理 矩阵树定理能求生成树个数的原因是,它本质上求的是: \[\sum_T \prod_{e\in T} w_e \] 其中 \(w_e\) 是边权,那么我们会发现其实 ...

  9. 题解 big

    传送门 题面里那个式子 考场上我推了半天那个式子代表什么意思,但就是没想到位运算 \(\lfloor \frac{2x}{2x^n} \rfloor \iff x\gg(n-1)\), 即将x的第n位 ...

  10. idea中使用docker插件部署项目

    安装docker 如果你之前安装过 docker,请先删掉 sudo yum remove docker docker-common docker-selinux docker-engine 安装一些 ...