一、背景
爱上Java诊断利器Arthas之Arthas idea plugin 前世今生,arthas 对于小哥来说,已经不可分割了,在我的日常开发、线上问题排查中扮演了非常重要的角色。作为小开发的我,日常需要排查线上运营同学提的各种bug、各种线上问题诊断、日常运维、线上问题优化等等一堆的问题。在刚刚来公司前期是比较恐惧运维任务的,代码不熟悉、各种问题比较多…几乎崩溃的状态,运维的一周基本上没有干活,完全是全投入到运维的任务中,排查问题效率低下,由于深刻体验这这种奔溃,一直想改变这种状态,直到arthas的开源,让我在这种崩溃的状态中减轻了不少负担…同时也让我成为了同事们咨询arthas 排查问题的小帮手~~一直关注着arthas的动态、关注着钉钉群消息大佬的解答,关注着横云断岭 大佬的博客。虽然使用arhtas 特别的方便,但是在此过程中也遇到一些问题,作为问题咨询小帮手也感到有点不方便,因此才造就了arthas idea 插件的诞生。
目前Arthas 官方的工具还不够足够的简单,需要记住一些命令,特别是一些扩展性特别强的高级语法,比如ognl获取spring context 为所欲为,watch、trace 不够简单,需要构造一些命令工具的信息,因此只需要一个能够简单处理字符串信息的插件即可使用。当在处理线上问题的时候需要最快速、最便捷的命令,因此Idea arthas plugin插件还是有存在的意义和价值的。—这个是最初编写这个插件的最核心的理由。
1.1 插件下载地址
https://plugins.jetbrains.com/plugin/13581-arthas-idea
1.2 github 地址
https://github.com/WangJi92/arthas-idea-plugin 缺星星~
user-case:https://github.com/WangJi92/arthas-idea-plugin/issues
使用文档:https://www.yuque.com/docs/share/fa77c7b4-c016-4de6-9fa3-58ef25a97948?#
1.3 本文使用demo 地址
https://github.com/WangJi92/arthas-plugin-demo
本文视频介绍大约 1hour,最好结合视频+文档学习+实践
优酷地址:https://v.youku.com/v_show/id_XNDYxMDUxMzYxNg==.html
1.4 相关功能
二、 自问自答
2.1 你有在使用arthas ?你们公司怎么使用的?
对啊,我们的公司经常使用,在预发环境中使用arhas 排查问题、在测试环境使用arhtas 排查问题、性能调优参考。
直接通过docker file中打包加入一个as.sh的shell 其实就是java -jar arthas-boot.jar,开发就可以执行as.sh启动脚本启动arthas 非常的方便,对于开发非常的友好,不需要了解细节问题。
2.2 你在学习arthas的过程,有过困惑?
对啊,我非常的困惑,arthas 提供的功能特别的多,跟着在线上的教程学习过程中非常爽,但是时间久了就记不住,一些复杂的场景需要打开小本本慢慢的看,然后一步步的处理,中间使用起来没有连续性。特别是高级的ognl 语法,没有仔细的学习一些特性真的很难搞懂,要想用得好,还得非常深入的学习,小本本得记住一些常用的功能。不然线上处理问题,需要速度…根本节奏跟不上。
2.3 作为小帮手,同事都问你啥?
没有特别多的,arthas的底层代码看了一点点,没有看完,基本的功能理解了太深入我也回答不上来,一般都是一些基础的功能,比如 怎么我想获取这个变量怎么使用?这个问题怎么用arhtas 排查呢?trace 一下?我想这个怎么办呢?这里得到一个结论:并不是每个人都是非常的关注arthas,对于arthas 的语法糖的使用并不是很care,我仅仅想快速的解决问题,一般就几个常用的功能即可,我就想用一个简单的功能,还要我记住这么多?这么麻烦,还不如打个log???
2.4 我在本地如何快速启动 arthas?
是否和我一样的迷茫?每次都有下载一个arthas-boot.jar ?其实我仅仅需要一个记住的命令即可,这里不是docker环境,是你本地的开发环境,我是如何解决的呢?小本本记录下来,复制粘贴(如果测试环境docker 中没有arhtas 粘贴执行一遍),通过alias 全局的记录一个命令 as.sh 启动即可,我都忘记了arthas 如何启动的…程序员都讨厌重复的劳动力。
curl -sk https://arthas.gitee.io/arthas-boot.jar -o ~/.arthas-boot.jar && echo "alias as.sh='java -jar ~/.arthas-boot.jar --repo-mirror aliyun --use-http'" >> ~/.bashrc && source ~/.bashrc
三、Arthas idea plugin 前世今生
3.1 使用前期
本人有个习惯,就是特别喜欢把东西通过文档的形式分享出来,在公司的内部分享了很多的文档,有的是技术文档、有的是使用文档、有的是记录文档等等,测试环境中docker 没有安装arthas ,又特别想使用arthas 嗯,那么按照上上面的bash 执行一下命令即可使用。比如安装脚本、watch 脚本、trace 脚本,下面的基本上就像我在公司内部编写的一个样子。使用前期基本上这几个命令是最常用的命令,其他的都没有使用。就这样分享我的文档,构建命令排查问题的时候先去按照这个命令copy reference 然后到vscode 上面进行编辑修改,然后到服务器上启动arthas 执行命令 一直这个样子。
安装脚本
curl -sk https://arthas.gitee.io/arthas-boot.jar -o ~/.arthas-boot.jar && echo "alias as.sh='java -jar ~/.arthas-boot.jar --repo-mirror aliyun --use-http'" >> ~/.bashrc && source ~/.bashrc
watch 查看入参返回值
watch 查看添加一些默认参数,比如-x 3 展开3层数据,估计部分同学不知道,打印参数值,返回值、异常{params,returnObj,throwExp},嗯你按照这个格式将右键copy refence #号去掉替换一下即可。
watch com.wangji92.arthas.plugin.demo.controller.StaticTest invokeStaticMethodParamObjListUser '{params,returnObj,throwExp}' -n 5 -x 3
trace 查看调用链
备注:这个只会对于当前方法生效,不会调用方法中调用的方法。
如果要再调用下一个方法使用
trace -E xxxAclass|xxxBClass xxMethod|xxx2Method 这样的规则 没有先后顺序
不跳过jdk的方法 --skipJDKMethod false
trace com.wangji92.arthas.plugin.demo.controller.StaticTest invokeStaticMethodParamObjListUser -n 5
退出
shutdown or stop
相关链接
快速入门:https://arthas.gitee.io/quick-start.html
进阶使用:https://arthas.gitee.io/advanced-use.html
用户案列:https://github.com/alibaba/arthas/issues?q=label%3Auser-case
3.2 使用中期
由于没事的时候逛逛arhtas github issue. 受到arthas ognl强大的影响,我开始关注这些特殊的用法了,对我的影响蛮大的,特别是获取spring context 为所欲为。然后小本本开始记录了,记录了这些相关的链接,在部门群开始分享,但是感觉关注度不行,由于这个还是有点复杂,难于记忆,还要认真的学习一下ognl 官方的文档,非常重要,了解其特性。watch 使用ognl 执行表达式、tt 时间隧道也是使用ognl 执行表达式,ognl 肯定也是,这样给与了很多强大的想想空间,ognl 语法十分强大。这样就开始了解执行静态方法、静态变量、调用方法等等,同时还扩展了通过ognl 获取静态的spring context (模仿了横云断岭大神的tt 获取spring context)然后调用方法、调用字段信息。还在小本本中记录一些场景的语法糖。那个时候真希望解决问题的时候语法糖就在脑海中哈哈,可惜我打字不够快…
- Arthas的一些特殊用法文档说明:https://github.com/alibaba/arthas/issues/71
- Alibaba Arthas实践–获取到Spring Context,然后为所欲为: https://github.com/alibaba/arthas/issues/482
- ognl 官方文档: https://commons.apache.org/proper/commons-ognl/language-guide.html
- ognl 实践:https://blog.csdn.net/u010634066/article/details/101013479
ognl static 调用字段、方法
@xxxclass@xxxmethod ,语法class 加载的classloder不一样,这里静态值也可能不一样,因此先要获取一下classloader的hash值,由于默认获取的是系统的classloader,由于这个关系,很多伙伴问我,so 按照教程来学习咯。
- 先获取classloader hash 值
sc -d com.wangji92.arthas.plugin.demo.controller.StaticTest
[arthas@4308]$ sc -d com.wangji92.arthas.plugin.demo.controller.StaticTest
class-info com.wangji92.arthas.plugin.demo.controller.StaticTest
code-source /Users/wangji/Documents/project/arthas-plugin-demo/target/classes/
name com.wangji92.arthas.plugin.demo.controller.StaticTest
isInterface false
isAnnotation false
isEnum false
isAnonymousClass false
isArray false
isLocalClass false
isMemberClass false
isPrimitive false
isSynthetic false
simple-name StaticTest
modifier public
annotation
interfaces
super-class +-java.lang.Object
class-loader +-org.springframework.boot.devtools.restart.classloader.RestartClassLoader@316bc132
+-sun.misc.Launcher$AppClassLoader@18b4aac2
+-sun.misc.Launcher$ExtClassLoader@4c6e276e
classLoaderHash 316bc132
- 然后根据语法糖 @xxxclass@xxxmethod
ognl -x 3 '@com.wangji92.arthas.plugin.demo.controller.StaticTest@INVOKE_STATIC_NAME' -c 316bc132
静态static spring context 调用方法、字段
由于受到"Alibaba Arthas实践–获取到Spring Context,然后为所欲为 :https://github.com/alibaba/arthas/issues/482" 这篇文章的影响,对于获取到spring context的强大感到十分的意外、甚至惊喜。但是这个使用起来通过tt 整个流程还是比较复杂,传递给同事估计不熟悉接收的程度十分的低下,需要进行两次才能进行调用,还是复杂,为何不能减少一次呢?我们的统一的jar包中有统一的一个静态的spring context :http://www.dcalabresi.com/blog/java/spring-context-static-class/
由于这个spring context 是静态的,那么一定是可以通过ognl 获取的,然后调用bean 就可以为所欲为了,进行各种惊喜操作。流程类似上面这个,不过需要小本本记录 自己按照格式进行替换想调用哪个bean的方法、字段。
public class ApplicationContextProvider implements ApplicationContextAware {
private static ApplicationContext context;
public ApplicationContext getApplicationContext() {
return context;
}
@Override
public void setApplicationContext(ApplicationContext ctx) {
context = ctx;
}
}
获取commonController这个bean 的这个方法进行调用
ognl -x 3 '#springContext=@com.wangji92.arthas.plugin.demo.common.ApplicationContextProvider@context,#springContext.getBean("commonController").getRandomInteger()' -c 316bc132
ognl 语法糖
如何使⽤arthas ognl 调⽤⽅法?⼀般在我们后端使⽤的都是spring 管理的,只需要获取Spring context即可操作处理,对于传递对象参数,传递Map ,传递List。ognl按照表达式的逗号分隔的顺序执⾏命令,⽀持链式调⽤,具体可以参 ognl 实践:https://blog.csdn.net/u010634066/article/details/101013479
Arthas的一些特殊用法文档说明:https://github.com/alibaba/arthas/issues/71
ognl 语法 #开头变量 在ognl 里面是变量全局的,可以传递 ;字段类型要注意 Doubble -> 1D,Long - >1L ,String ->’’, class对象->@xxxClass@class 相当于一个静态的变量
List 参数
#listObject={"a","b"}
Lists.newArrayList("a","b")
map 参数
#mapObject= #{"key","value"}
Map<String,String> map = new HashMap();
map.put("key",value);
array 参数
#array=new java.lang.String[]{"1"}
String[] array = new String[1];
array[0]="1";
obj 参数
调用构造函数
#obj = new xxxxClass();
xxxxClass obj = new xxxxClass();
Class 对象参数
ognl -x 3 '@com.wangji92.arthas.plugin.demo.controller.StaticTest@invokeClass(@com.wangji92.arthas.plugin.demo.controller.StaticTest@class)' -c 482503f0
public static String invokeClass(Class classN) {
if (classN == null) {
return "";
}
return classN.getName();
}
复杂对象构造
由于#user=new com.wangji92.arthas.plugin.demo.controller.User(),构造了一个全局的ognl值,对于当前执行的ognl 链中,因此可以在最后的使用,其他的场景就可以自由的发挥了。#user.setName(“wangji”) 设置参数的值,然后放置在List的参数中,invokeStaticMethodParamObjListUser(0,{#user,#user}) 这种复杂的场景,真的需要很理解ognl的语法知识点。不然完全懵了。认真看arthas userCase 中有很多的东西、干货。
ognl -x 3 '#user=new com.wangji92.arthas.plugin.demo.controller.User(),#user.setName("wangji"),#user.setAge(27L),@com.wangji92.arthas.plugin.demo.controller.StaticTest@invokeStaticMethodParamObjListUser(0,{#user,#user})' -c e374b99
public static String invokeStaticMethodParamObjListUser(Integer number, List<User> names) {
if (number == null) {
number = 1;
}
if (names == null) {
names = Collections.EMPTY_LIST;
}
return number + names.toString();
}
期间小插曲(spring shell)
在这个使用的过程中,深刻的烦恼着copy 这些语法糖,但是使用最多的任然是trace watch ,一般情况下都是那几个默认的参数即可,想着能不能够自动化一下子,同事经常使用scala的交互式命令写了一些场景中常见的命令,这个arthas的东西能不能也这样子呢?好像是可行的。这个也用了一段时间,挺好用的哈哈,直到有天看到了一个博客介绍编写IDEA 插件,一语惊醒梦中人,为何不把这个中间的过程去掉呢?支持更多的功能,让这个功能更加的流畅起来呢?简单的功能需要有,如果就是现在的at、aw、as 估计我不会去想着学习编写一个插件的,因为我还想着更多的自动化,比如 static -c 参数能不能连续性?static spring context 能不能连续性?固话下来呢?一些思考,和小伙伴讨论了一下子,就在周末学习学习开动了起来。
IDEA->Copy Refence (剪切板)->Spring shell 命令行解析字符串 -> 转换成arthas的语法糖
为此还去学习了一下子spring shell的相关文档,记录一下学习遇到的问题 ,还写了一篇博客介绍命令行中收集了我学习的一些工具 参考链接 Java程序员的命令行工具-spring shell 命令行,Arthas 线上运维
arthas
ai, arthasInstall: arthas 安装脚本
arthasStatic, as: 获取类的静态字段,变量(-c classLoaderHash 默认值 SystemClassLoader)[ sc -d com.test 获取 classLoaderHash 值]
arthasTable: arthas 学习(各种特殊链接)
arthasTrace, at: trace 某个方法的调用栈
arthasWatch, aw: watch 某个方法的入参返回值
3.3 使用后期
后期由于开发arthas idea plugin 插件的功能愈来愈具备连贯性、简化性 基本上简单的通过文档学习一下,实操一遍之后不会忘记如何使用,右键点开即可使用。如今的功能小编在不断的跟进着arthas 官方的命令,将一些有可能集成进来的功能都进行了集成,还集成了一些高级的功能哈,有好滴idea 可以通过github 联系我,进行处理。
最近为了参与arthas的征文活动,写了一个github arthas idea plugin 的demo,也是本文的一个重要的demo,后续的实践都是跟着这个demo 进行实践 :https://github.com/WangJi92/arthas-plugin-demo
四、arthas idea plugin 实践
arthas 插件下载地址 : https://plugins.jetbrains.com/plugin/13581-arthas-idea ,或者直接通过idea 进行下载。
功能列表
功能点非常的多,这里就不一一的去讲解,可以参考使用文档 ,不过最近一直在更新,使用文档中的命令名称可能有变化
4.1 安装 install
这个很简单的就是做了一个alias 然后jar -jar 启动arthas-boot.jar
curl -sk https://arthas.gitee.io/arthas-boot.jar -o ~/.arthas-boot.jar && echo "alias as.sh='java -jar ~/.arthas-boot.jar --repo-mirror aliyun --use-http'" >> ~/.bashrc && source ~/.bashrc
4.2 获取static 变量
和最初的一样,首先要获取classloader的hash 值,然后获取命令,这个是一个交互流程需要连贯性,后续只要是static 的通过static spring context的都需要有这个交互的流程,连贯的,都在同一个界面进行操作.粘贴执行,然后获取结果即可。
这里的classloader的hash 值缓存起来的
最后合并的脚本如下。
ognl -x 3 '@com.wangji92.arthas.plugin.demo.controller.StaticTest@INVOKE_STATIC_NAME' -c 316bc132
4.3 反射设置static field
通过反射进行设置static field ,参考:https://github.com/WangJi92/arthas-idea-plugin/issues/1
填写你想要修改的值、默认根据类型设置默认值 Str->"" Long -> 0L 等等。
ognl -x 3 '#field=@com.wangji92.arthas.plugin.demo.controller.StaticTest@class.getDeclaredField("INVOKE_STATIC_FINAL"),#modifiers=#field.getClass().getDeclaredField("modifiers"),#modifiers.setAccessible(true),#modifiers.setInt(#field,#field.getModifiers() & ~@java.lang.reflect.Modifier@FINAL),#field.setAccessible(true),#field.set(null,"设置的值")' -c 316bc132
4.4 spring context invoke
通过spring context 进行调用bean的方法、字段的内容。
Static Spring Context Invoke Method Field
首页要设置一下static spring context的路径
由于都是通过ognl 调用static的spring context 都需要classloader,这个就是配置的spring conetxt的地址信息:
@com.wangji92.arthas.plugin.demo.common.ApplicationContextProvider@context 参考demo 就需要配置这个地址。
ognl -x 3 '#springContext=@com.wangji92.arthas.plugin.demo.common.ApplicationContextProvider@context,#springContext.getBean("commonController").getRandomInteger()' -c 316bc132
Watch Spring Context Invoke Method Field
watch 这个是支持在spring mvc场景 通过watch 间接的获取spring context,需要出发一次接口的调用,可以参考 :https://github.com/WangJi92/arthas-idea-plugin/issues/5
watch -x 3 -n 1 org.springframework.web.servlet.DispatcherServlet doDispatch '@org.springframework.web.context.support.WebApplicationContextUtils@getWebApplicationContext(params[0].getServletContext()).getBean("commonController").getRandomInteger()'
TimeTunnel Spring Context Invoke Method Field
这个是参考了横云断岭 的arthas 通过tt 获取spring context 为所欲为 ,可以参考这个文档:https://github.com/WangJi92/arthas-idea-plugin/issues/4 这里做了些什么?将整个连贯了起来,不需要记住参数信息,然后对于调用的参数进行简单的默认封装,复杂的参数场景不支持,需要手动拼接,参考上面的ognl 语法糖。
记录获取spring context
tt -t org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter invokeHandlerMethod
然后根据这个target 获取spring context 调用方法
tt -w 'target.getApplicationContext().getBean("commonController").getRandomInteger()' -x 3 -i 1000
4.5 获取某个spring 环境变量
获取spring 环境变量这里依托,static spring context ,当然这个watch 、和 tt 获取spring context的场景也是支持的。在线上环境、测试环境程序多复杂,你怎么知道环境中的变量一定是你配置的?在nacos等等配置中心的场景,估计手速慢了一点点,可能就没有上去,这个时候就有这种需求获取当前的环境变量。选中变量,然后右键执行命令。由于使用静态的static spring context 依然需要classloader的值.这里已经基本上是arthas的上层应用啦。
ognl -x 3 '#springContext=@com.wangji92.arthas.plugin.demo.common.ApplicationContextProvider@context,#springContext.getEnvironment().getProperty("custom.name")' -c 316bc132
4.6 获取全部的spring 环境变量
比较优先级,最前面的一定优先级最高,你一定被spring的各种优先级顺序搞晕了,那么怎么办呢?arthas idea plugin 支持获取当前的全部的环境变量,依次打印出来**,这样就可以了解优先级,**特别是接入了nacos、diamond等远程的配置中心,实现不一样肯定更晕了。参考文档:https://blog.csdn.net/xunjiushi9717/article/details/94050139
ognl -x 3 '#springContext=@com.wangji92.arthas.plugin.demo.common.ApplicationContextProvider@context,#allProperties={},#standardServletEnvironment=#propertySourceIterator=#springContext.getEnvironment(),#propertySourceIterator=#standardServletEnvironment.getPropertySources().iterator(),#propertySourceIterator.{#key=#this.getName(),#allProperties.add(" "),#allProperties.add("------------------------- name:"+#key),#this.getSource() instanceof java.util.Map ?#this.getSource().entrySet().iterator.{#key=#this.key,#allProperties.add(#key+"="+#standardServletEnvironment.getProperty(#key))}:#{}},#allProperties' -c 316bc132
4.7 TimeTunnel Tt
方法执行数据的时空隧道,记录下指定方法每次调用的入参和返回信息,并能对这些不同的时间下调用进行观测(可以重新触发,周期触发,唯一缺点对于ThreadLocal 信息丢失[隐含参数]、引用对象数据变更无效),这个方便二次触发,特别是自己调试不方便的情况下记录下来,二次触发、周期触发,不过自从段岭大神tt 为所欲为之后都被带偏了。这里arthas 插件做了一些什么?增加了二次触发的一些常用的命令,不让使用者愁于记忆,整个过程更加的具有连贯性。
4.8 stack 堆栈
获取方法从哪里执行的调用栈(用途:源码学习调用堆栈,了解调用流程) 这个是非常好用的功能,对于喜欢乐于排查问题的小伙伴真是福音,arthas idea 插件只是修改的命令的集成,之前也处理自己编码过程中的问题,源码、问题排查技巧-Java Debug and Arthas: https://blog.csdn.net/u012881904/article/details/104591529
stack com.wangji92.arthas.plugin.demo.controller.CommonController getRandomInteger -n 5
4.9 Decompile Class Jad
反编译方法、类的源码, 有时候需要查看提交的代码是否上线呢?这个功能就非常的友好。参考文档:https://github.com/WangJi92/arthas-idea-plugin/issues/2
jad --source-only com.wangji92.arthas.plugin.demo.controller.CommonController getRandomInteger
4.10 watch、trace
增加了默认参数、默认展开的层级 限制次数,使用者不用知道这些核心的参数,简单的使用就好了,要使用更加的高级的自己help 一下就知道了。
watch com.wangji92.arthas.plugin.demo.controller.CommonController getRandomInteger '{params,returnObj,throwExp}' -n 5 -x 3
trace com.wangji92.arthas.plugin.demo.controller.CommonController getRandomInteger -n 5
4.11 trace -E(层级的打印trace)
这个trace -E 是龙哥给我提的需求,确实有这样的需求,自己构造起来非常的麻烦,通过界面操作简化了一下,需要观察多个类、多个方法的场景。选择你需要的场景继续添加即可。
trace -E com.wangji92.arthas.plugin.demo.controller.CommonController|com.wangji92.arthas.plugin.demo.service.ArthasTestService traceE|doTraceE -n 5
4.12 Heap Dump
打印堆栈,有点类似 jmap -dump:format=b,file=/temp/dump.hprof pid 下载下来使用MAT分析即可。
heapdump /tmp/dump.hprof 打印堆栈信息
4.13 特殊用法链接
这个必须要说一下,这个特殊用法的链接在线上自己束手无措的时候可以查看一下,非常有用。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OmGOee9a-1585489441774)(https://cdn.nlark.com/yuque/0/2020/png/171220/1585414323919-6882bc6e-d6c3-4384-8c7f-9511ca525ff2.png#align=left&display=inline&height=555&name=image.png&originHeight=1110&originWidth=2078&size=925057&status=done&style=none&width=1039)]
4.14 对于通过spring context 调用方法说明
通过spring context 调用复杂的方法其实是不支持的,由于这个操作起来不方便,还是必须手工处理一下。
比如这里的 Map<String, User> names 的处理方式可以借鉴一下子。更多可以参考demo https://github.com/WangJi92/arthas-plugin-demo
/**
* 复杂参数调用 场景
* static spring context
* ognl -x 3 '#user=new com.wangji92.arthas.plugin.demo.controller.User(),#user.setName("wangji"),#user.setAge(27L),#springContext=@com.wangji92.arthas.plugin.demo.common.ApplicationContextProvider@context,#springContext.getBean("commonController").complexParameterCall(#{"wangji":#user})' -c e374b99
*
* watch get spring context 备注 需要调用一次方法
* watch -x 3 -n 1 org.springframework.web.servlet.DispatcherServlet doDispatch '#user=new com.wangji92.arthas.plugin.demo.controller.User(),#user.setName("wangji"),#user.setAge(27L),@org.springframework.web.context.support.WebApplicationContextUtils@getWebApplicationContext(params[0].getServletContext()).getBean("commonController").complexParameterCall(#{"wangji":#user})'
*
* tt get spring context ,only first get time index ok
* tt -w '#user=new com.wangji92.arthas.plugin.demo.controller.User(),#user.setName("wangji"),#user.setAge(27L),target.getApplicationContext().getBean("commonController").complexParameterCall(#{"wangji":#user})' -x 3 -i 1000
* @return
*/
@RequestMapping("complexParameterCall")
@ResponseBody
public String complexParameterCall(@RequestBody Map<String, User> names) {
if (names == null) {
return "EMPTY";
}
return names.toString();
}
五、总结
本文简单的介绍了arthas idea plugin 诞生的前世今生的故事,解放了大家对于arthas 使用的一些记忆、机械性的重复工作,欢迎大家的使用,有需求可以联系我,尽量的满足。
更多汪小哥