WangJi92 / arthas-idea-plugin

arthas idea plugin 更简单的使用arthas的IDEA 插件,方便的构建各种arthas 命令,复制到剪切板 然后到服务器上启动arthas 执行命令。
https://plugins.jetbrains.com/plugin/13581-arthas-idea
Apache License 2.0
597 stars 98 forks source link

arthas 构建 vmtool & ognl & spring context.getBean 等命令入参支持复杂类型 JSON 转换 #127

Open anjia0532 opened 5 months ago

anjia0532 commented 5 months ago

Vmtool Get Instance Invoke Method Field 为例,对于简单的基础类型可以直接写,但是对于自定义类型则相对麻烦些。

插件默认给 vmtool -x 3 --action getInstances --className 类 --express 'instances[0].方法(new 类())' -c classload hash

OGNL 的方式


vmtool -x 3 --action getInstances --className 类  --express '#p=new 类(),#p.setFieldA("参数A"),instances[0].方法(#p)'  -c classload hash
# 解释一下
# 定义参数 #p=new 类()
# 调用方法进行赋值 #p.setFieldA("参数A")
# 方法入参 instances[0].方法(#p)
# 多个语句之间用英文逗号隔开

Json 的方式

我个人更喜欢用这种方式

# hutool
vmtool -x 3 --action getInstances --className 类  --express 'instances[0].方法(@cn.hutool.json.JSONUtil@toBean("{\"fieldA\":\"参数A\"}",类.class))'  -c classload hash

# fastjson
vmtool -x 3 --action getInstances --className 类  --express 'instances[0].方法(@com.alibaba.fastjson.JSONObject@parseObject("{\"fieldA\":\"参数A\"}",类.class))'  -c classload hash

是否考虑再简化下操作?比如自动生成全了。人工只填写参数就行了。

WangJi92 commented 5 months ago

@anjia0532 idea 很不错,之前也考虑过这个参数问题,现在的实现相对比较简单

anjia0532 commented 5 months ago

因为json反序列化框架太多了,都兼容不太现实,要么类似 spring bean 那样,让用户自己配置反序列化类和方法。工具这块只是实现将用户贴入的json压缩(json min 化,去掉换行符,string字符串内的换行符替换成 \n ,将""替换成\"\")。好处简单替换下,可以格式化。开发人员阅读起来更方便。

要么是默认实现第一种,#p=new 类(),#p.方法(参数),......, 调用(#p) 这种实现起来更简单些,但是对于一些大类,没法格式化,肉眼看比较费事。

WangJi92 commented 4 months ago

工程实现

解析流程

序列化框

序列化框架查找当前工程中存在的 FastJson>JackJson>Gson

样例

样例支持情况还挺多的,只要不是泛型(ognl 不支持泛型),基本是都没有问题,为了支持这个命令,arthas 插件反向支持了一个可以反向生产Clazz的JSON 字符串的命令。

单User

vmtool -x 3 --action getInstances --className com.wangji92.arthas.plugin.demo.controller.CommonController  --express 'instances[0].userFastJson(@com.alibaba.fastjson.JSON@parseObject("{\"name\":\" \",\"age\":0}",@com.wangji92.arthas.plugin.demo.controller.User@class))'  -c  2c95c2c2

List

User[]

Map<String,User>

总结

基本上这个命令功能,基本上实现完毕,还有写小缺陷需要自测一下,就可以发布了

WangJi92 commented 4 months ago

@anjia0532 你看看呢?

WangJi92 commented 4 months ago

Set 不支持 ,其实还可以这么写?

 @PostMapping("/userFastJson233")
  @ResponseBody
  public Object userFastJsonSet(@RequestBody Set<User> user) {

      return user;
  }

userFastJsonSet((#set=new java.util.HashSet(),#set.add(JSON解析的结果),#set)

vmtool -x 3 --action getInstances --className com.wangji92.arthas.plugin.demo.controller.CommonController  --express 'instances[0].userFastJsonSet((#set=new java.util.HashSet(),#set.add(@com.alibaba.fastjson.JSON@parseObject("{\"name\":\"wnagji\",\"age\":0}",@com.wangji92.arthas.plugin.demo.controller.User@class)),#set))'  -c 197a18de 
anjia0532 commented 4 months ago

奈斯

@anjia0532 你看看呢?

WangJi92 commented 4 months ago

ognl 不支持泛型,如何骚操作处理复杂参数?

ognl 不支持泛型?

如何处理?

 /**
     *  处理这种泛型复杂参数 TestGeneratesClazz<String,Map<String,User>> test
     *  1、ognl 本身不支持泛型参数
     *  2、通过Json 构建外层对象 TestGeneratesClazz
     *  3、获取TestGeneratesClazz所有泛型参数
     *  4、遍历TestGeneratesClazz 所有字段 包含了泛型参数 且非基本类型,通过判断是否有set方法进行赋值 同理赋值使用json 构造
     *  5、构建脚本 差异化解决无法处理泛型的问题..
     * @param param
     * @return
     */
    public Object testParam(TestGeneratesClazz<String,Map<String,User>> param) {
        return param;
    }
vmtool -x 3 --action getInstances --className com.wangji92.arthas.plugin.demo.controller.CommonController  --express 'instances[0].testParam((#p=@com.alibaba.fastjson.JSON@parseObject("{\"user2\":{\"name\":\" \",\"age\":0},\"integer\":0,\"st\":\" \",\"user\":\" \",\"test\":{\"_key_\":{\"name\":\" \",\"age\":0}}}",@com.wangji92.arthas.plugin.demo.controller.TestGeneratesClazz@class),(#p.setUser(@com.alibaba.fastjson.JSON@parseObject("{\"user2\":{\"name\":\" \",\"age\":0},\"integer\":0,\"st\":\" \",\"user\":\" \",\"test\":{\"_key_\":{\"name\":\" \",\"age\":0}}}",@com.wangji92.arthas.plugin.demo.controller.TestGeneratesClazz@class))),(#p.setTest(@com.alibaba.fastjson.JSON@parseObject("{\"user2\":{\"name\":\" \",\"age\":0},\"integer\":0,\"st\":\" \",\"user\":\" \",\"test\":{\"_key_\":{\"name\":\" \",\"age\":0}}}",@com.wangji92.arthas.plugin.demo.controller.TestGeneratesClazz@class))),#p))'  -c 6f54e410
WangJi92 commented 4 months ago

浏览器 JSON 插件

JSON-handle

WangJi92 commented 4 months ago

json 压缩 转义

https://www.json.cn/jsonzip/ 这个工具比较方便点

anjia0532 commented 4 months ago

非广哈,如果不介意安装三方工具(而不是打开网页的话),我个人更推荐 https://u.tools/download/ 支持 win/mac/linux 。类似时间戳转换,json格式化,压缩,翻译,加解密等等有很丰富的插件。不用费劲收藏各类工具网站 image image

WangJi92 commented 4 months ago

@anjia0532 这个工具 我也有安装哈哈 OCR识别很爽

anjia0532 commented 4 months ago

有个蛋疼的小tips,如果要用JSON序列化反序列化,注意检查下参数里有没有字段上加了 @JsonIgnore@JSONField(serialze=false) 等注解。否则会出现反序列化不传值的问题。

WangJi92 commented 4 months ago

有个蛋疼的小tips,如果要用JSON序列化反序列化,注意检查下参数里有没有字段上加了 @JsonIgnore@JSONField(serialze=false) 等注解。否则会出现反序列化不传值的问题。 这里干掉了.. image

anjia0532 commented 4 months ago

嗯,我不是说插件会把本该忽略的字段带上,而是针对用户说的,在用的过程中,遇到死活传不进的值,看看有没有加这个注解。

WangJi92 commented 4 months ago

嗯,我不是说插件会把本该忽略的字段带上,而是针对用户说的,在用的过程中,遇到死活传不进的值,看看有没有加这个注解。

这个是JSON 工具限制的 ~ 忽略了

anjia0532 commented 3 months ago

@WangJi92 非广哈,新版的 arthas 的 json 序列化我体验了,但是感觉 Cool Request 的调用体验更好一些。

普通入参 image

对象入参 image

WangJi92 commented 3 months ago

@anjia0532 这个侧重点不一样,这个http请求,我喜欢用官方 Idea HTTP Client ,arthas 这个是反向构造一个json 字符串,用来写文档之类的