故事背景
飞测群里有同学,又提了一个乱码的问题—request请求提的乱码。各种配置修改,都不能解决。乱码现象如下图:
解决思路
1、修改本地配置文件
因为此处的数据,还没有发送出去,所以,肯定是这个变量的编码和jmeter内部的一些编码不一致导致。然后,尝试修改jmeter.properties的配置项:
`sampleresult.default.encoding=utf-8`
重启jmeter后,依然还是乱码。
2、修改消息头和请求体编码
同时把消息头和请求体的编码修改为utf-8,结果依然不生效。
3、查看jmeter源码
<1>因为是request请求体的内容,所有先在下面的包中进行查看:
org.apache.jmeter.visualizers
然后看到一个java的接口文件:
RequestView.java
<2>这个接口中有一个下面的方法:
JPanel getPanel();
通过eclipse,找到实现这个接口的函数(右键->Quick Type Hierarchy查找)。搜索到如下2个文件:
RequestViewRaw.java
RequestViewHTTP.java
<3>因为乱码是在http视图先出现的,Raw并没有出现,所以推测应该在RequestViewHTTP.java文件中可以找到线索。大致阅读了下源码,找到如下内容:
public static String decodeQuery(String query) {
if (query != null && query.length() > 0) {
try {
query = URLDecoder.decode(query, CHARSET_DECODE); // better ISO-8859-1 than UTF-8
} catch(IllegalArgumentException e) {
log.warn("Error decoding query, maybe your request parameters should be encoded:" + query, e);
return null;
} catch (UnsupportedEncodingException uee) {
log.warn("Error decoding query, maybe your request parameters should be encoded:" + query, uee);
return null;
}
return query;
}
return null;
}
其中下面一句是关键:
query = URLDecoder.decode(query, CHARSET_DECODE); // better ISO-8859-1 than UTF-8
对请求体的内容进行了url编码。于是,检查常量CHARSET_DECODE的值。如下:
private static final String CHARSET_DECODE = "ISO-8859-1"; //$NON-NLS-1$
因为之前的尝试步骤中,把所有的配置都修改为了UTF-8,那么,是不是因为这个地方的编码为ISO-8859-1,不一致,所致?尝试修改配置如下:
private static final String CHARSET_DECODE = "UTF-8"; //$NON-NLS-1$
重新编译。执行jmeter。成功!截图如下:
发散一下
为什么jmeter的开发人员留下如此的注释:
better ISO-8859-1 than UTF-8 (好奇)
搜索后的理解:
1、ISO-8859-1(Latin-1),单字节编码,是一种8位字符集,占位少。
2、ISO-8859-1能够满足所有的欧洲语言(开发者是个用欧洲语言的人呗)。
那UTF-8是什么呢:
1、亚洲和非洲语言并不能被8位字符集所支持,只有用2个字节,才可以编码地球上几乎所有地区的文字,因此,创建了UNICODE编码。
2、UNICODE比ASCII占用大一倍的空间,而对ASCII来说高字节的0对他毫无用处,应运而生了新的编码形式–UTF(Unicode Transformation Format)
3、UTF-8:每次8个位传输数据,它是一种变长的编码方式。当字符在ASCII 码的范围时,就用一个字节表示,保留了ASCII字符一个字节的编码做为它的一部分,注意的是unicode一个中文字符占2个字节,而UTF-8一个中 文字符占3个字节。(此点,不是很清楚)