Bean Shell 介绍:
-
BeanShell是一种完全符合Java语法规范的脚本语言,并且又拥有自己的一些语法和方法;
-
BeanShell是一种松散类型的脚本语言(这点和JS类似);
-
BeanShell是用Java写成的,一个小型的、免费的、可以下载的、嵌入式的Java源代码解释器,具有对象脚本语言特性,非常精简的解释器jar文件大小为175k。
-
BeanShell执行标准Java语句和表达式,另外包括一些脚本命令和语法。
官网地址:http://www.BeanShell.org/
Jmeter 使用到 BeanShell 的组件:
-
定时器: BeanShell Timer
-
前置处理器: BeanShell PreProcessor
-
采样器: BeanShell Sampler
-
后置处理器: BeanShell PostProcessor
-
断言: BeanShell断言
-
监听器: BeanShell Listener
Beanshell的内置变量和方法
段落引用Beanshell有一些默认的内置变量和方法,用户可以通过这些变量与JMeter进行交互,例如:
print:非GUI模式下打印信息(输出信息到stdout,标准输出控制台)。
log:输出信息到日志(文件)
日志打印级别:
-
log.debu(“调试信息”)
-
log.info(“响应状态码” + ResponseCode)
-
log.warn(“警告信息”)
-
log.error(“出错信息”)
获取响应变量:
-
ResponseCode:响应状态码(String类型)。
-
ResponseHeaders:响应头(String类型)。
获取请求结果:
-
prev:获取当前请求结果
-
prev.getResponseDataAsString():获取响应体数据(String类型)。
-
prev.getResponseCode():获取状态码(同ResponseCode,String类型)。
jmeter变量(线程内生效):
-
vars:操作JMeter变量
-
String var1 = vars.get(“变量名”):获取变量的值(假设为String类型)。
-
vars.put(“变量名”, 变量值):设置变量值。
-
jmeter内置函数 ${变量名}
jmeter属性(可跨线程):
-
props:操作JMeter属性
-
props.get(String,String) 可以获取JMeter中已经生成的属性。
-
props.put(String,String)可以创建和更新JMeter属性。
-
jmeter内置函数 ${__property(变量名)} 或 ${__P(变量名)}
线程上下文:
-
ctx:获取当前线程上下文数据(可获取所有信息)
-
ctx.getVariables(“变量名”):获取变量值(同vars.get())。
-
ctx.setVariables(“变量名”, “变量值”):设置变量(同vars.put())。
-
ctx.getProperties(“属性名”):获取属性值(同props.get())。
-
ctx.setProperties(“属性名”,“属性值”):设置属性(同props.put())。
-
ctx.getPreviousResult():获取当前请求结果同(prev)。
-
ctx.getCurrentSampler():获取当前采样器。
-
ctx.getPreviousSampler():获取前一采样器。
-
ctx.getThreadNum():获取线程数。
-
ctx.getThreadGroup():获取线程组。
-
ctx. getThread():获取当前线程。
-
ctx.getEngine():获取引擎。
-
ctx.isSamplingStarted():判断采样器是否启动。
-
ctx.isRecording():判断是否开启录制。
-
ctx.getSamplerContext():获取采样器山下文数据。
示例演示:
需模拟下图中的get请求,其中sign是通过代码生成的,如若每次请求前,都复制入参去编译器生成将十分麻烦,此时可考虑使用beanshell。
编译器中调试代码:
将代码复制进BeanShell取样器中调试:
import java.io.*;
import java.net.URLEncoder;
import java.util.*;
import java.security.*;
import java.math.BigInteger;
public class MySign {
//获取签名字符串
public static String getSign(String appId,String channelId,String deviceId,String dateStart,String dateEnd,String periodId,String signKey){
HashMap map = new HashMap();
map.put("appId",appId);
map.put("channelId",channelId);
map.put("deviceId",deviceId);
map.put("dateStart",dateStart);
map.put("dateEnd",dateEnd);
map.put("periodId",periodId);
String signStr = genSign(map, signKey);
return signStr;
}
// md5算法
public static String md5(String plainText) {
byte[] secretBytes = null;
try {
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(plainText.getBytes("utf-8"));
secretBytes = md.digest();
} catch (NoSuchAlgorithmException | UnsupportedEncodingException e) {
throw new RuntimeException("no such algorithm!");
}
String md5code = new BigInteger(1, secretBytes).toString(16);
int length = md5code.length();
for (int i = 0; i < 32 - length; i++) {
md5code = "0" + md5code;
}
return md5code;
}
// 签名算法
public static String genSign(HashMap<String, String> params, String signKey) {
String result = "";
try {
List<Map.Entry<String, String>> infoIds = new ArrayList<Map.Entry<String, String>>(params.entrySet());
Collections.sort(infoIds, new Comparator<Map.Entry<String, String>>() {
public int compare(Map.Entry<String, String> o1, Map.Entry<String, String> o2) {
return (o1.getKey()).toString().compareTo(o2.getKey());
}
});
// 构造签名键值对的格式
for (Map.Entry<String, String> item : infoIds) {
if (item.getKey() != null || item.getKey() != "") {
String key = item.getKey();
String val = item.getValue();
if (result == "") {
result += key + "=" + URLEncoder.encode(val, "UTF-8");
} else {
result += "&" + key + "=" + URLEncoder.encode(val, "UTF-8");
}
}
}
// System.out.println(result);
} catch (Exception e) {
throw new RuntimeException("error");
}
// System.out.println(signKey+result);
return md5(signKey + result);
}
}
String sign = new MySign().getSign("${appId}","${channelId}","${deviceId}","${dateStart}","${dateEnd}","${periodId}","signKey");
vars.put("Sign",sign);
调试结果:
BeanShell不支持java泛型,编译不通过。
不支持java泛型的解决方案:
1、优化代码,不使用泛型。(复杂代码不推荐)
2、代码封装成jar包,在通过BeanShell引入使用。(简单粗暴,推荐)
①、从idea 将代码打包jar包:
②、测试计划中引入jar包依赖:
③、BeanShell 中导入调用类方法:
④、测试是否调用成功:
完成。
评论区