shannonredeemed

Jmeter JSR223+Groovy创建、赋值与解析HashMap变量

一、源起

这是一篇为了解决工作脚本中的HashMap变量解析问题,而做的探究

二、安装Jmeter

(一)、首先检查机子上是否有安装 jdk

检查方式,在 cmd 中输入 java -version,出现如下信息,即已经安装好 jdk

 检查Java JDK环境变量【这是另外一件事情,如果我啥时候有了新的电脑,没有安装过jdk,那么认真查考相关教程再来补充这个地方吧~~~】

(二)、安装Jmeter

1、下载Jmeter (切记:一定要下载Binaries 下面的文件,而不是Source下面的!!!)

https://jmeter.apache.org/download_jmeter.cgi  

 

2、 解压 Jmeter 安装包

3、 配置Jmeter环境变量

注意:JMETER_HOME不是必须配置,因为有时候这个路径代言,会引起Jmeter.bat访问失灵,本tip也可作为启动Jmeter排查方案

按下面变量名和变量值配置 Jmeter 系统环境变量:
【变量名】JMETER_HOME
【变量值】D:\Program Files\apache-jmeter-5.6.3(jmeter 解压路径)
【变量名】CLASSPATH
【变量值】% JMETER_HOME%\lib\ext\ApacheJMeter_core.jar;% JMETER_HOME%\lib\jorphan.jar;% JMETER_HOME%\lib\log4j-core-2.22.1.jar;

【变量名】Path 

【变量值】在原值末尾加;然后补充======%JMETER_HOME%\bin======进去,为了能够在开始菜单中输入jmeter.bat启动程序。

三、启动Jmeter,并开始调试脚本

(一)、启动Jmeter

(二)、解决启动警告

1、识别警告

遇到了WARN警告,DS一下,说是当前版本用【扫描包】的方式来定位插件位置的办法已经被deprecated,而且即将在未来的版本中移除,我需要安装Plugins Manager插件来解决这个问题。(本以为可以带着这个问题继续,但后续进入脚本调试时,遇到了不得不解决这个问题的情况——我需要Custom JMeter Functions插件中提供的getObject功能,所以现在将解决方案列在这里)

2、解决警告

进入官网https://jmeter.apache.org/,找不到下载Plugins Manager插件的位置,于是,又请DS给出详细的下载地址,答案在此↓↓↓

https://jmeter-plugins.org/install/install 下面,点击箭头所指位置即可下载(注意:网络不太好使,下载可能比较慢,但链接是可用的,建议多尝试

 插件下载成功后,放入 %JMETER_HOME%\lib\ext 目录,重启Jmeter(警告仍会存在,但可以忽略了),选项/Options菜单下应该出现 Plugins Manager 选项

(三)、调整偏好设置

1、 界面风格及颜色 - 菜单设置,即可固定

image

 

2、 语言设置 - 临时 或者 固定

临时的话,菜单设置即可,但重启Jmeter后,界面语言会恢复默认的英文。

image

 

固定的话,需要修改配置文件

image

 

(四)、调试脚本

1 、 需求及DS方案

  1/* ***  ==================需求================
  2 我现在的前置脚本中,已经用vars.putObjcet("s_dict")存储了一个HashMap变量,它在调试取样器中打印的值如下:
  3 s_dict={div=450300, seqStr='S001', 'S002'}
  4 我在后续的JSR223组件中如何获取这个变量,并使用它的值呢?
  5 *** */
  6 
  7 // =======================DS方案======================
  8 在 JMeter 中直接通过 `vars.putObject()` 存储的对象需要使用对应的 `vars.getObject()` 方法获取。以下是详细的操作步骤和注意事项:
  9 
 10 ---
 11 
 12 ### 1. **获取并验证对象**
 13 ```groovy
 14 // 直接获取对象(假设已通过 vars.putObject 存储)
 15 def sDict = vars.getObject("s_dict")
 16 
 17 // 类型安全检查
 18 if (sDict instanceof Map) {
 19 log.info("✅ 成功获取HashMap对象,类型: " + sDict.getClass().name)
 20 log.info("完整内容: " + sDict.toString())
 21 } else {
 22 log.error(" 变量 s_dict 不是Map类型,实际类型: " + (sDict?.getClass()?.name ?: "null"))
 23 throw new Exception("无效的s_dict类型")
 24 }
 25 ```
 26 
 27 ---
 28 
 29 ### 2. **访问Map中的值**
 30 ```groovy
 31 // 方式1:Groovy属性风格(推荐)
 32 def divCode = sDict.div
 33 def seqStr = sDict.seqStr
 34 
 35 // 方式2:传统Map.get()
 36 def divCode = sDict.get("div")
 37 def seqStr = sDict.get("seqStr")
 38 
 39 // 使用值示例
 40 log.info("行政区划码: ${divCode}")
 41 log.info("序列字符串: ${seqStr}")
 42 
 43 // 注意键的引号问题(调试器中显示 div=450300 的键未加引号)
 44 // 实际存储时Groovy会自动处理键的字符串类型,无需担心
 45 ```
 46 
 47 ---
 48 
 49 ### 3. **处理调试器中显示的问题**
 50 你的调试取样器显示:
 51 `s_dict={div=450300, seqStr='S001', 'S002'}`
 52 这里可能存在两个问题:
 53 
 54 1. **键名引号缺失**
 55 `div` 和 `seqStr` 作为键时,Groovy默认会处理为字符串,但最后的 `'S002'` 可能被误解析为值而不是键,说明原始Map构造可能有误。
 56 
 57 2. **键值对数量异常**
 58 显示的键值对数量不匹配(似乎有3个元素但只有两个键),需检查存储时的Map构造代码。
 59 
 60 ---
 61 
 62 ### 4. **修正原始Map的构造代码**
 63 检查你的前置脚本中的Map创建代码,确保键值对正确:
 64 ```groovy
 65 // 错误示例(导致键不明确)
 66 def badMap = [div:450300, seqStr:'S001', 'S002'] // 第三个元素缺少键名!
 67 
 68 // 正确写法
 69 def correctMap = [
 70 div: 450300,
 71 seqStr: "S001",
 72 nextSeq: "S002" // 明确指定键名
 73 ]
 74 
 75 // 存储修正后的Map
 76 vars.putObject("s_dict", correctMap)
 77 ```
 78 
 79 ---
 80 
 81 ### 5. **跨线程组传递对象**
 82 如果需要在 **不同线程组** 中使用该对象,需改用 `props` 代替 `vars`:
 83 ```groovy
 84 // 存储
 85 props.putObject("GLOBAL_s_dict", sDict)
 86 
 87 // 获取(任意线程组)
 88 def globalDict = props.getObject("GLOBAL_s_dict")
 89 ```
 90 
 91 ---
 92 
 93 ### 6. **备用方案(兼容性更强)**
 94 如果 `getObject()` 不可用(如未安装插件),改用 **JSON序列化** 95 ```groovy
 96 // --------- 前置脚本 ---------
 97 import groovy.json.JsonBuilder
 98 
 99 def sDict = [div: 450300, seqStr: "S001", nextSeq: "S002"]
100 vars.put("s_dict", new JsonBuilder(sDict).toString())
101 
102 // --------- 后续脚本 ---------
103 import groovy.json.JsonSlurper
104 
105 def jsonStr = vars.get("s_dict")
106 def sDict = new JsonSlurper().parseText(jsonStr) as Map
107 ```
108 
109 ---
110 
111 ### 常见问题排查表
112 
113 | 现象 | 原因 | 解决方案 |
114 |------|------|----------|
115 | `getObject()` 返回 `null` | 1. 变量名拼写错误<br>2. 对象未正确存储 | 1. 检查变量名大小写<br>2. 确认前置脚本已执行 |
116 | 类转换异常 | 实际存储的不是Map类型 | 检查前置脚本中的 `putObject` 数据类型 |
117 | 键不存在错误 | 键名错误或Map构造错误 | 使用 `sDict.containsKey("div")` 检查键是否存在 |
118 
119 ---
120 
121 通过以上方法,你可以安全地在 JMeter 的 Groovy 脚本间传递复杂对象。如果问题仍然存在,建议:
122 1. 在前置脚本中添加 `log.info("存储的对象类型: " + sDict.getClass())`
123 2. 确保 JMeter 版本 ≥ 5.0 并安装了 **Plugins Manager** 中的 **Custom JMeter Functions** 插件(提供 `putObject/getObject` 支持)

 

2 、 根据DS方案,编写脚本请求代码

 1 // 第一个JSR223 + Groovy请求
 2 import java.util.HashMap
 3 
 4 def seq_dict = [:]
 5 
 6 seq_dict.put("div","450300")
 7 seq_dict.put("seqStr","'S001','S002'")
 8 
 9 vars.putObject("seq_dict",seq_dict)
10 
11 
12 
13 // 第二个JSR223 + Groovy请求
14 import java.util.HashMap
15 
16 def aMap = vars.getObject(seq_dict)? : new HashMap()
17 
18 String str = Map.get("450300")
19 
20 vars.put("str",str)

2、报错及问题排查

上述脚本执行报错如下:

结合DS给的方案及常见错误,排查如下:

(1)缺少Custom JMeter Functions插件——

通过 Plugins Manager 安装Custom JMeter Functions插件

 重启后,仍然报原来的错误,有点崩溃,继续检查——

(2)发现第二个请求里,定义的是aMap变量,但使用的是Map变量。。改正。但改正后仍然报错。

(3)判断创建 和 获取的变量类型是否为Map,修改代码如下:

 1 // 第一个请求
 2 import java.util.HashMap
 3 
 4 def seq_dict = new HashMap()
 5 
 6 if (seq_dict instanceof Map) {
 7     seq_dict.put("div","450300")
 8     seq_dict.put("seqStr","'S001','S002'")
 9     vars.putObject("seq_dict",seq_dict)
10     vars.put("valid","true")
11 } else {
12     vars.put("valid","false")
13 }
14 
15 
16 // 第二个请求 ====》 加上try catch 异常捕获逻辑
17 import java.util.HashMap
18 
19 try {
20     def aMap = vars.getObject("seq_dict")
21     if (aMap instanceof Map) {
22         String str = aMap.get("450300")
23         vars.put("str",str)
24         vars.put("validObt","true")
25     } else {
26         vars.put("validObt","false")
27     }
28     
29 } catch (Exception e){
30     log.error("Failed to getObject" + e.getMessage())
31 }

执行后,竟然不报错了!!!但是没有获取到 str值……

 (4)再次浏览DS给的方案,发现它提到我的键值对存储有问题,一段调整,如下代码,竟然获取到k-v中的 value值了

// 修改第一个请求
import java.util.HashMap

def seq_dict = new HashMap()

if (seq_dict instanceof Map) {
    seq_dict.put("450300","'S001','S002'") // 这里调整了 K-V的添加方式
    seq_dict.put("210000","'A001'") // 添加第二组数据
    vars.putObject("seq_dict",seq_dict)
    vars.put("valid","true")
} else {
    vars.put("valid","false")
}


// 修改第二个请求
import java.util.HashMap

String dd = "450300"

try {
    def aMap = vars.getObject("seq_dict")
    if (aMap instanceof Map) {
        if (aMap.containsKey(dd)){
            String str = aMap.get(dd)
            vars.put("str",str)
        }
        vars.put("validObt","true")
    } else {
        vars.put("validObt","false")
    }
    
} catch (Exception e){
    log.error("Failed to getObject" + e.getMessage())
}

 3 、 更新需求

 1 /* ***
 2 
 3 我需要将获取到的 str中的字符串 用 , 分割,分割后,返回一个字符串数组,并需要计算该数组的长度
 4 
 5 *** */
 6 
 7 // =====================代码=====================
 8 
 9 // 第一个请求
10 import java.util.HashMap
11 
12 def seq_dict = new HashMap()
13 
14 if (seq_dict instanceof Map) {
15     seq_dict.put("450300","'S001','S002'")
16     seq_dict.put("210000","'A001'")
17     vars.putObject("seq_dict",seq_dict)
18     vars.put("valid","true")
19 } else {
20     vars.put("valid","false")
21 }
22 
23 
24 // 第二个请求
25 import java.util.HashMap
26 
27 // 条件获取键值对
28 String dd = "450300"
29 
30 try {
31     def aMap = vars.getObject("seq_dict")
32     if (aMap instanceof Map) {
33         if (aMap.containsKey(dd)){
34             String str = aMap.get(dd)
35             vars.put("str",str)
36             // 将获取的 str 按, 分割,获取字符串数组strArr
37             List<String> strArr = str.split(",")
38             // 将获取的字符串数组转换成字符串,检查分割结果
39             vars.put("strArr",strArr.toString() )
40                         // 并计算 字符串数组长度
41             vars.put("count", strArr.size().toString())
42         }
43         vars.put("validObt","true")
44     } else {
45         vars.put("validObt","false")
46     }
47     
48 } catch (Exception e){
49     log.error("Failed to getObject" + e.getMessage())
50 }    

 

执行成功了啊!!!!!竟然成功了………………

 

四、祈祷明天把调试结果应用到工作脚本顺利……

阿门!

 

———————————————

Jmeter安装及配置部分参考链接:https://learnku.com/articles/43858

 

posted on 2025-03-23 19:06  Shannon_Zhang  阅读(211)  评论(0)    收藏  举报