1、乱码产生原因
web服务默认解码字符集,通常来说均为utf8或gbk。以Tomcat为例,conf/server.xml配置gbk编码
<Connector port="80" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" URIEncoding="GBK"/>
当请求参数用utf8编码时,后台接收到的str参数即为乱码
请求地址:/test?str=%e4%bd%a0%e5%a5%bd
Tomcat自动进行URLDecoder.decode(str, “gbk”)处理
接收结果:浣犲ソ
2、修正乱码
2.1、判断乱码
方式1
原理:utf8乱码进行gbk字节<->字符转换后,会发生变化;反之gbk乱码进行utf8转换亦然
input.equals(new String(input.getBytes("gbk"), "gbk"));
方式2
原理:utf8乱码无法进行gbk编码;反之gbk乱码进行utf8编码亦然
java.nio.charset.Charset.forName("GBK").newEncoder().canEncode(input);
方式3:
利用utf8编码规则,将原始参数转为byte进行校验
由于方式1效率最高,故采用此方式校验
2.2、示例
enum ProCharset {UTF8, GBK}
@ResponseBody
@GetMapping("/test")
public void test(String str) {
System.out.println("START:" + str);
if (!checkDisCode(str, ProCharset.UTF8)) {
str = restore(request.getQueryString(), "str", ProCharset.UTF8);
}
System.out.println("END:" + str);
}
/**
* 校验字符串是否乱码
*
* @param input 待校验字符串
* @param proCharset web服务字符集
* @return 校验结果
*/
private static final boolean checkDisCode(String input, ProCharset proCharset) {
if (isEmpty(input)) {
return true;
}
String charset = "gbk";
if (proCharset == ProCharset.GBK) {
charset = "utf-8";
}
try {
return input.equals(new String(input.getBytes(charset), charset));
} catch (Exception e) {
return false;
}
}
/**
* 恢复乱码
*
* @param queryStr 查询参数
* @param paramName 待恢复参数
* @param proCharset web服务字符集
* @return 处理结果
*/
private static final String restore(String queryStr, String paramName, ProCharset proCharset) {
if (!isEmpty(queryStr) && !isEmpty(paramName)) {
String charset = "gbk";
if (proCharset == ProCharset.GBK) {
charset = "utf-8";
}
for (String param : queryStr.split("&")) {
if (param.startsWith(paramName + "=")) {
try {
return URLDecoder.decode(param.split("=")[1], charset);
} catch (Exception e) {
return queryStr;
}
}
}
}
return queryStr;
}
/**
* 校验字符串是否为空
*
* @param str 字符串
* @return 校验结果
*/
private static final boolean isEmpty(String str) {
if (str == null || str.equals("")) {
return true;
} else {
return false;
}
}
测试(web服务为utf8编码)
请求1:/test?str=%c4%e3%ba%c3%b0%a1
输出结果:
START:��ð�
END:你好啊
请求2:/test?str=%e4%bd%a0%e5%a5%bd%e5%95%8a
输出结果:
START:你好啊
END:你好啊
乱码已被成功修正,正常字符无影响