大家用jmeter最常遇到的是请求参数中文乱码问题(至于返回值乱码问题由于处理简单也不影响测试,就不在这里说了),而对于这个问题,很多人不能从根本上去分析和理解,所以就无法从根本上去回避和解决,以下我就通过几种情况来分别说明:
在这之前,先做好测试案例:
(1)准备CSV数据文件,内容只有三列:1,test,测试
注意:这里的文件名含路径,linux下必须是csvData/ID2.csv(如果用反斜杠,在linux下就找不到文件,而jmeter4.0非常糟糕的一点是正斜杠保存完后也会变成反斜杠,只能通过编辑器批量修改,为了避免麻烦,可以不用像我这样,只要把脚本和csv保存在bin下就行,这样只需要输入文件名ID2.csv即可)。
(2)分别准备三个请求,这三类请求基本覆盖了常见的参数化乱码问题
一个是在请求名称中带所有参数,用的是BeanShell
一个是key-value参数格式的请求
一个是Body Data格式的请求
下面我们就可以开始测试了。
场景一:默认ANSI/ASCII格式的参数化文件
我们在设置CSV数据文件时,文件编码置空不做选择,进行测试后发现在windows下两请求编码正常(第3个请求后面再说):
而在Linux下却是乱码
我们做一下设置,在设置CSV数据文件时,加上GBK编码
这时再测试,就会发现linux下和windows下都正常编码了。
注释:设置CSV数据文件,编码项是可选的,但不一定会有GBK选项,要么手填,要么修改jmeter.properties
场景二:用UTF-8格式的参数化文件(最好是用编辑器保存为UTF-8 无bom头)
同样默认情况下设置CSV数据文件时,文件编码置空不做选择
我们将UTF-8格式的ID2.csv同时覆盖到windows和linux下进行测试
我们发现windows下显示乱码了
而linux下却正常了
同样我们做一下设置,在设置CSV数据文件时,加上UTF-8编码
保存后再进行测试,发现windows下和linux下都正常了
通过以上两个场景的对比测试,我们发现一个道理,就是设置CSV数据文件时,文件编码的配置是在告诉jmeter,将以什么编码格式显示参数文件的数据,如果不配置即按操作系统的默认编码格式显示(windows下是GBK或gb2312,linux下是UTF-8)。而一旦出现显示的编码格式与csv文件的编码格式不统一时,就会出现乱码。为了避免错乱,我们就统一将CSV保存为UTF-8格式,统一在设置CSV数据文件的面板中,文件编码选择UTF-8。
场景三:对Body Data格式请求的中文参数测试
在确保以上两个场景的问题处理完后,我们是否就解决了乱码问题,答案是否定的。因为以上的方式只是保证jmter发送的URL请求格式不会有乱码,但不能保证body或json中是否没有乱码。在前两个请求都正常的情况下,我们在看看第三个请求的结果:
为什么会这样,我们通过解开jmeter的源代码,就能找到答案(以下是节选PostWriter.java中的两段源码):
public static final String ENCODING = StandardCharsets.ISO_8859_1.name();
public String sendPostData(URLConnection connection, HTTPSamplerBase sampler) throws IOException {
// Buffer to hold the post body, except file content
StringBuilder postedBody = new StringBuilder(1000);
HTTPFileArg[] files = sampler.getHTTPFiles();
String contentEncoding = sampler.getContentEncoding();
if(contentEncoding == null || contentEncoding.length() == 0) {
contentEncoding = ENCODING;
}
//此处省略代码.......
return postedBody.toString();
}
通过以上代码可以看出,PostData是需要设置编码格式的,而且默认编码字符是ISO_8859_1(第一行代码),编码读取的是Content Encoding,这个在jmeter的http请求面板上就能看到。我们配置成UTF-8试试:
发现还是乱码,但是这个乱码能看出已经能够识别出utf-8字符了:
这也说明了编码还是不一致,死记万能的UTF-8是行不通的,我们换个GBK或gb2312试试:
正常显示中文了!!!!!
场景四:还有种编码叫URLEncoder
不是所有的请求,直接发送中文就能正常得到响应,这还要取决于web应用服务端的相关编码处理。先了解一下什么是URLEncoder:url编码是一种浏览器用来打包表单输入的格式。浏览器从表单中获取所有的name和其中的值 ,将它们以name/value参数编码(移去那些不能传送的字符,将数据排行等等)作为URL的一部分或者分离地发给服务器。
为了避免明文发送中文或是去除/转译非法字符,URL编码是非常必要的,在http请求中对URL参数进行URL编码的方式如下(勾选编码):
进行URL编码后的请求效果如下:
当然也可以通过BeanShell PreProcessor来实现对{name}参数URL编码,如下:
vars.put("name",URLEncoder.encode("${name}","UTF-8"));
有了编码,就有解码URLDecoder.decode,这是在应用服务端实现的。我们也可以在jmeter上模拟解码过程,如下:
vars.put("name",URLDecoder.decode("${name}","utf-8"));
针对中文参数化的编码问题,我们就举这四个场景,当然解决的方式不仅限于上面所罗列的。思路是一样的,方法是多样的,包括直接修改jmeter的源码,重新编译一个你自己的jmeter也行。通过以上的方式,我们也发现utf-8编码是相对通用的,因为在linux下和windows下都能得到相应的解决和处理。
附:其他注意事项
1、默认linux可能不支持中文,可以通过以下方式简单处理:
编辑i18n配置文件: vi /etc/sysconfig/i18n
进行如下配置并保存退出:
#LANG="en_US.UTF-8"
LANG="zh_CN.UTF-8"
SYSFONT="latarcyrheb-sun16"
执行以下命令即时生效
source /etc/sysconfig/i18n
2、在linux下对于jmeter的csv参数文件不要命名为ID.CSV
原因不明,至少在jmeter4.0下测试发现了问题,这样命名的文件,要么是发送消息为乱码,要么是读取不到参数。
3、将csv参数统一为UTF-8编码是解决编码兼容性的好办法,以下提供一个我自己写的在linux下批量转换csv为utf-8编码的脚本:
#!/bin/bash
### 将 values_here 替换为输入编码
#FROM_ENCODING="value_here"
### 输出编码 (UTF-8)
TO_ENCODING="UTF-8"
### 转换命令
#CONVERT=" iconv -f $FROM_ENCODING -t $TO_ENCODING"
### 使用循环转换多个文件
for file in *.csv; do
rm -f ${file%.csv}.csv.bak #先清理备份文件
mv ${file%.csv}.csv ${file%.csv}.csv.bak #转换前先备份文件
#以下为获取csv文件的原编码格式
FROM_ENCODING=$(file -i ${file%.csv}.csv.bak | awk '{print $3}' | sed '1s/charset=//g')
#对于识别不了的编码暂时归为GBK
if [ "$FROM_ENCODING" = "unknown-8bit" ];then
FROM_ENCODING=$(echo "GBK")
fi
CONVERT=" iconv -f $FROM_ENCODING -t $TO_ENCODING"
$CONVERT "${file%.csv}.csv.bak" -o "$file"
#$CONVERT "$file" -o "${file%.csv}.csv"
done
exit 0
将脚本放在csv文件目录下,给脚本赋可执行权限,执行完后就能将当前目录下的csv编码格式全转成utf-8