Jmeter的BeanShell实在太不友好了,没有提示也看不了源码,支持的java版本也低,所以在使用Jmeter进行一些稍复杂的处理时就很难受。
签名方式
获取Json的所有键-值对,以&
方式进行拼接,再进行Md5加密获得签名。json格式的值为字符串,如:
detail=[{"cellNo":"aaaa","unitNo":"bbbb","rackNo":"cccc","count":3,"realCount":3}]
参数格式
{
"appId": "string",
"timestamp": "string",
"nonce": "string",
"signature": "string",
"clusterNo": "string",
"orderNo": "string",
"detail": [
{
"rackNo": "string",
"unitNo": "string",
"cellNo": "string",
"count": 0,
"realCount": 0
}
]
}
纯BeanShell处理
import org.apache.jmeter.config.Arguments;
import org.apache.jmeter.config.Argument;
//import org.json.JSONObject;
//import org.json.JSONArray;
import org.apache.commons.codec.digest.DigestUtils; //导入md5加密的包
import java.text.SimpleDateFormat; //获取时间戳
import com.alibaba.fastjson.*;
// 1.获取请求body值,并处理字符串
Arguments arguments = sampler.getArguments();
Argument arg = arguments.getArgument(0);
String body = arg.getValue();
//log.info(">>>>>>>>>>>>>>>>>{}",body);
body=body.replaceAll("\\n|\\r|\\t","");
log.info(">>>>>>>>>>>>>>>>>body{}",body);
// 2.将body字符串转换成JSONObject,并添加固定的参数和appSecret
JSONObject body_jsonObj= JSONObject.parseObject(body); //包;org.json.JSONObject,没有该静态方法
//JSONObject body_jsonObj = new JSONObject(body);
//log.info("..........>"+body_jsonObj.get("detail").toString());
String appSecret=vars.get("appSecret"); //appSecret信息
String timestamp=(System.currentTimeMillis()/1000).toString(); //10位时间戳a信息
String nonce=vars.get("nonce"); //nonce信息
String appId=vars.get("appId"); //nonce信息
body_jsonObj.put("appSecret",appSecret);
//body_jsonObj.put("timestamp",timestamp);
//body_jsonObj.put("nonce",nonce);
//body_jsonObj.put("appId",appId);
log.info("..........yy>"+body_jsonObj.get("detail").toString());
// 4.获取json的键数组,并升序排列
Set body_keys = body_jsonObj.keySet();
Object[] arr=body_keys.toArray();
//Arrays.sort(arr,Collections.reverseOrder()); //降序
Arrays.sort(arr); //升序
//for(Object value:arr)
//{
//log.info(value.toString());
//}
// 5.按照方式“键=值” 拼接json的所有键值对
StringBuffer sb=new StringBuffer();
for (Object key : arr){
String value = null ==body_jsonObj.get(key) ? "":body_jsonObj.get(key).toString();
log.info(key+"="+value);
sb.append(sb.toString().length()==0?key+"="+value:"&"+key+"="+value);
}
log.info("-----------------4444");
String signString = sb.toString();
log.info(signString);
// 5.md5加密,得到sign签名值
String md5_after = DigestUtils.md5Hex(signString); // md5加密
log.info(md5_after);
// 6.给jsonObject对象添加sign参数,并移除appSecret信息
body_jsonObj.put("signature", md5_after.toUpperCase());
body_jsonObj.remove("appSecret");
// 7.JSONObject 转字符串
String postData = body_jsonObj.toString();
log.info(postData);
// 8.重新赋值请求的body参数
arg.setValue(postData);
这种方式获取的签名字符串格式是正确的,但是detail
值的参数顺序会被打乱,而签名时是严格按照参数顺序来进行,所以签名会失败。经过验证,json.jar
(20231023)的JSONObject body_jsonObj = new JSONObject(body)
和fastjson.jar
(1.2.62)的JSONObject body_jsonObj= JSONObject.parseObject(body);
都会改变参数顺序,由于没装java开发工具,不好研究方法参数。
导入外部文件
- java文件无包依赖
可以直接调用,如:
source("D:\\Java\\Jmeter\\JSONTool.java");
log.info("--------------6666:"+JSONTool.Add(1,2));
public class JSONTool {
public static int Add(int a,int b) {
return a+b;
}
}
-
java文件有包依赖
需要将java项目打包成jar文件,并且在测试计划中添加该外部资源,这里是vsc打包。
-
序列化排序
使用fastjson.jar
,在字段上添加@JSONField(ordinal=x)
,即可实现按照指定字段顺序序列化,参考连接:JSON序列化后按对象中声明顺序序列化或者指定顺序序列化(Java)
@JSONField(ordinal = 1)
public String rackNo;