您的位置:首页 > 其它

终极解决GET方式中文乱码

2017-01-14 23:35 232 查看


问题:

 想重定向到错误提示页面, 并带上错误信息, 实现方式是统一的controller异常处理器, 拦截到异常, 获取异常响应类型是Rest(@ResponseBody)还是页面, 若是页面, 则重定向到统一的错误页面, 带上自定义异常的错误信息, 问题来了. 若是中文错误信息, 在异常处理器中拿redirectAttribute好困难啊, 为了实现统一和松耦合, 决定使用get方式, 结果问题更严重的乱码
首先第一步URLEncode.encode中文(页面的话用JS函数也可以编码), 组装url跳转到错误提示Controller, 入参一定是乱码, 正常情况下new String(message.getBytes("ISO8859-1"),"UTF-8")转回来即可, 这取决于Tomcat的默认编码, 也可以改Tomcat编码解决. 

原因:
        但没这么简单, 错误消息为测试, 转码后为%E6%B5%8B%E8%AF%95,   跳转异常action组装的url为: tips/complete?success=false&message=%E6%B5%8B%E8%AF%95
结果action入参为测è¯
        一看就像是转译字符, 找了半天原因是springmvc入参解析器绑定一个转义处理:
webDataBinder.registerCustomEditor(String.class, new PropertyEditorSupport() {
@Override
public void setAsText(String text) {
setValue(text == null ? null : StringEscapeUtils.escapeHtml4(text.trim()));
}

@Override
public String getAsText() {
Object value = getValue();
return value != null ? value.toString() : null;
}
});
经过整理大致逻辑为:
1. String src = "测试";
2. src = URLEncoder.encode(src);
3. System.out.println(src); // 转码后变为%E6%B5%8B%E8%AF%95 -> 传到服务器变为 æµè¯
4. src = StringEscapeUtils.escapeHtml4(src);
5. System.out.println(src); // æµè¯ 变为 æµè¯ 变成这个就不可逆了~~~
第三步传到服务器后乱码可以理解, tomcat使用iso8859编码字符造成的
第四步经过参数解析器绑定的转义处理直接将乱码转义成废屁~~~

解决:
解决想法有了, 在第四步和第三步之间转码, 当然那是不可能的, 受限于框架, 除非你仅仅写个demo, 否则你得花大把时间重写解析器~~~~

想了半天, 能否把%E6%B5%8B%E8%AF%95原样带回, 而不让Tomcat转成测è¯这么个飞机呢~~~
首先想到Tomcat.server.xml, 改吗? 改了不就成小学生了~~

Google了下URLDecoder.encode的原理, 决定两次编码, 看:
String src = "测试";
src = URLEncoder.encode(src);
System.out.println(src); // 第一次变为: %E6%B5%8B%E8%AF%95
src = URLEncoder.encode(src);
System.out.println(src); // 第二次变为: %25E6%25B5%258B%25E8%25AF%2595 -> 传到服务器是不变的
src = StringEscapeUtils.escapeHtml4(src);
System.out.println(src); // 转义不会改变, 因为没得特殊字符
src = URLDecoder.decode(src);
System.out.println(src); // 第一次解码变为; %E6%B5%8B%E8%AF%95
src = URLDecoder.decode(src);
System.out.println(src); // 第二次解码变为: 测试


完美解决~~~

实际web环境, 两次编码后请求, 服务器只需一次解码即可, 原因是tomcat还是按照ISO8859-1将%25E6%25B5%258B%25E8%25AF%2595解码为字符%E6%B5%8B%E8%AF%95, 你拿到%E6%B5%8B%E8%AF%95后在解码一次就是中文了, 所以两次的编码后一次解码你用默认的字符集即可, 不要指定UTF-8
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  中文乱码 乱码