Arthas的一个重要应用场景是查看运行时数据,但有时需要动态查看数据,或者数据过多,需要动态过滤,复杂的规则需要依靠OGNL。
以下是一些常见的arthas中的ognl操作。 测试代码如下。 springboot工程:
@requestmapping(send ) ) publicstringsend ) httpservletrequestrequest,http servlet response returndosend ) cretureture } publicstringdosend (listuser userlist,boolean flag ) system.out.println ) ' dosend '; 返回' success '; }private ListUser createUserList () { ListUser userList=new ArrayList ); for(longI=0; i 10; I ) { User user=new User (; user.setid(I; user.setusername('u'I ); Userlist.add(user; } return userList; } class user { privatestring username; 私有long id; 公共字符串获取名称((return username ); } publicvoidsetusername (string username ) { this.username=username; } public Long getId () { return id; }publicvoidsetid(longid ) { this.id=id; } private String convert () { return id '_' username; }第n个参数watchcom.example.http client demo.httpclientdemoapplicationsend ' params [0] ' pressqorctrlctoabort.affect [ cost=0.267515 ms ] result=@ request facade [ request=@ request [ org.Apache.catalina.connector.request @ 518 AAA aa sm=@ string manager [ org.Apache.Tomcat.util.RES.string manager @6ffbca 2e ], ]参数的属性watchcom.example.http client demo.httpclientdemoapplicationsend ' params [0].class.name ' pressqorctrlctoabbbblctoation [ cost=0.252717 ms ] result=@ string [ org.Apache.catalina.connector.request facade ] 参数的方法返回值watchcom.example.http client demo.httpclientdemoapplicationsend ' params [0].get method (' pressqorctrlctrlcond [ cost=0. 289059 ms ] result=@ string [ get ]投影(Across )简单来说,就是查看集合中元素的属性或方法的返回值。 和lambda的地图非常相似
watchcom.example.http client demo.httpclientdemoapplicationdosend ' params [0].{ # this.username } '-B-x2 presssqore method-cnt:1 ) cost in28 ms.ts=2019-09-26153360193333301 [ cost=0.006187 ms ] result=@ ArrayList [ @ string ]
], @String[u4], @String[u5], @String[u6], @String[u7], @String[u8], @String[u9],]还可以在投影中调用方法
watch com.example.httpclientdemo.HttpclientDemoApplication doSend 'params[0].{#this.convert()}'Press Q or Ctrl+C to abort.Affect(class-cnt:2 , method-cnt:1) cost in 83 ms.ts=2019-09-26 15:30:04; [cost=0.349277ms] result=@ArrayList[ @String[0_u0], @String[1_u1], @String[2_u2], @String[3_u3], @String[4_u4], @String[5_u5], @String[6_u6], @String[7_u7], @String[8_u8], @String[9_u9],] 在观察表达式里过滤 watch com.example.httpclientdemo.HttpclientDemoApplication doSend 'params[0].{? #this.id > 8}' -b -x 2Press Q or Ctrl+C to abort.Affect(class-cnt:2 , method-cnt:1) cost in 33 ms.ts=2019-09-26 15:23:10; [cost=0.006812ms] result=@ArrayList[ @User[ username=@String[u9], id=@Long[9], ],] 过滤后计数 watch com.example.httpclientdemo.HttpclientDemoApplication doSend 'params[0].{? #this.username.endsWith("9")}.size()'Press Q or Ctrl+C to abort.Affect(class-cnt:2 , method-cnt:1) cost in 27 ms.ts=2019-09-26 15:33:12; [cost=0.165327ms] result=@Integer[1]这里需要分清楚,在条件表达式里写过滤条件和直接在观察表达式里写过滤条件的区别:
条件表达式过滤的是一次调用,判断该次调用能否返回观察表达式里的过滤,过滤的是该次调用的数据,不管怎么写,该次调用一定返回当然也可以在条件表达式里写 Ongl,效果是类似的:
watch com.example.httpclientdemo.HttpclientDemoApplication doSend 'params[0].{#this.username}' 'params[0].{? #this.id>7}.size()>0'Press Q or Ctrl+C to abort.Affect(class-cnt:2 , method-cnt:1) cost in 39 ms.ts=2019-09-26 15:45:12; [cost=0.19965ms] result=@ArrayList[ @String[u0], @String[u1], @String[u2], @String[u3], @String[u4], @String[u5], @String[u6], @String[u7], @String[u8], @String[u9],] 子表达式计算 watch com.example.httpclientdemo.HttpclientDemoApplication doSend 'params[0].size().(#this>5? 20+#this:10+#this)'Press Q or Ctrl+C to abort.Affect(class-cnt:2 , method-cnt:1) cost in 52 ms.ts=2019-09-26 15:58:36; [cost=0.179407ms] result=@Integer[30] 选择第一个匹配项 watch com.example.httpclientdemo.HttpclientDemoApplication doSend 'params[0].{^#this.username.startsWith("u")}' -b -x 2Press Q or Ctrl+C to abort.Affect(class-cnt:2 , method-cnt:1) cost in 141 ms.ts=2019-09-26 17:18:01; [cost=0.41405ms] result=@ArrayList[ @User[ username=@String[u0], id=@Long[0], this$0=@HttpclientDemoApplication$$EnhancerBySpringCGLIB$$10ddbd36[com.example.httpclientdemo.HttpclientDemoApplication$$EnhancerBySpringCGLIB$$10ddbd36@d5d5b7f], ],] 选择最后一个匹配项 watch com.example.httpclientdemo.HttpclientDemoApplication doSend 'params[0].{$#this.username.startsWith("u")}' -b -x 2Press Q or Ctrl+C to abort.Affect(class-cnt:2 , method-cnt:1) cost in 84 ms.ts=2019-09-26 17:18:32; [cost=0.036367ms] result=@ArrayList[ @User[ username=@String[u9], id=@Long[9], this$0=@HttpclientDemoApplication$$EnhancerBySpringCGLIB$$10ddbd36[com.example.httpclientdemo.HttpclientDemoApplication$$EnhancerBySpringCGLIB$$10ddbd36@d5d5b7f], ],] 调用静态方法 watch 时调用静态方法watch com.example.httpclientdemo.HttpclientDemoApplication doSend '@java.lang.Thread@currentThread()'Press Q or Ctrl+C to abort.Affect(class-cnt:2 , method-cnt:1) cost in 31 ms.ts=2019-09-26 17:20:29; [cost=0.13471ms] result=@TaskThread[ log=@DirectJDKLog[org.apache.juli.logging.DirectJDKLog@2f1ab57a], creationTime=@Long[1569484802267],]ognl 调用静态方法
注意:ognl 会受 classloader 的限制,如果在 tomcat 之类的环境下,会找不到对应的类
ognl 获取静态属性
ognl '@com.example.httpclientdemo.SpringApplicationContextHolder@isDestroyed'getstat 获取静态属性
getstatic com.example.httpclientdemo.SpringApplicationContextHolder applicationContext