最近在实际工作的两个项目中都遇到了乱码问题,虽然没有对乱码实际性问题有深刻理解,不过对于现象倒是有了一二的端倪观察,现在把自己的解决思路共享一下。
我将乱码问题归类为4种情况:
第一种:两个页面之间或者页面与后台之间参数传递,一个request请求传递到另一个页面或者后台,在接收到参数进行中文处理时,出现了乱码。乱码的问题出现大概也有这样几种情况,这种情况多见于前台用form传递参数:
1)文件编码不统一造成的,如一个页面是gb2312,一个页面是utf-8,甚至于有的人会在一个页面设置两个编码格式;这种情况最好办,文件编码统一就好了。
2)浏览器默认的编码格式与后台处理编码存在不一致。常见的浏览器默认处理编码"ISO8859-1",处理起来也很简单,基本上利用以下编程可以解决:
// 自定义字符串selfDefStr
selfDefStr = new String(selfDefStr .getBytes("ISO8859-1"), "UTF-8");
3)前两种组合,这个实际情况发生也很多。
第二种:传递的url中包含参数,参数含有中文,多见于直接地址传参,或者json格式传递参数,这种情况出现中文乱码,多是由于浏览器版本造成的,经测试,firefox和谷歌浏览器传递中文时,只要利用前面提到的第一种2)的解码方法即可解决,但对于ie浏览器,先要对ie进行编码操作才行,通过js encode方法 ,进行16进制编码,旨在将中文编程遗传英文支持良好的字符,传递到后台时信息不会错乱。
String temStr= URLEncoder.encode(selfDefStr, "UTF-8");
firefox和谷歌同样可以编码后传递,这样保证方式统一,无需判断(注ie只在ie8以上测试过)
有的文章说在java后台(侧)需要利用java的decode方法进行解码,经本人测试,后台解码反而乱码,直接使用第一种2)的解码方法进行处理反而通过,所以在此只告诉大家本人是如此解决的。万一如此解决是乱码,大家记得前台编码,后台可以解码这种方案即可。
第三种:插件给java后台(jsp)传递参数,比如本人集成金格公司的网页版电子签章,该空间只适用于ie下使用,封装成ocx,需要activex调用。由于参数值控件提供,无法知道正确的参数值是多少。解决方法最终是一样的,也是如下方法,只不过要知道控件的预编码格式,如金格是gb2312,而本人工程默认是utf-8,就不能转成utf-8:
// 自定义字符串selfDefStr
selfDefStr = new String(selfDefStr .getBytes("ISO8859-1"), "GB2312");
这里值得一提的是,由于本人不知道参数传递是什么形式,解决方法是,利用抓包工具来查看参数,本人推荐用fidder,具体使用本人就不赘述了,可以看到request请求信息,不如头信息,编码格式等,不过编码格式的信息本人认为这种方式意义不大,它代表的是传递过来的页面的编码格式,跟控件无关,最好是询问控件出品方编码格式,如果联系不到只能猜了,但是抓包的数据还是有利于我们对于数据一致性进行明确。抓包界面如下:
可以看到左边是每次请求,右边是请求传递的参数。该值意义重大,可以多分析几次,看看是否每次传递不同,窥探控件端倪。
第四种:由于统一的编码过滤器造成的乱码。统一过滤器的好处是对所有页面统一中文转码,基本上不会出现中文乱码的情况,但是总有例外,像第三种情况,总有一些特殊页面参数来源不同,编码格式不同,利用过滤器反而进行了一次过滤转码,造成后台处理时,如何处理也不对,这种情况,就要排除个别页面,不让其转码。因为这种情况往往被忽视,特别提出,共享大家。参数excludedPages(自定义)即为排除。 web.xml
<filter>
<filter-name>SetCharacterEncoding</filter-name>
<filter-class>com.horizon.filter.encoding.SetCharacterEncodingFilter</filter-class>
<!-- 用户请求和响应的编码设置程序 -->
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>ignore</param-name>
<param-value>false</param-value>
</init-param>
<init-param>
<param-name>excludedPages</param-name>
<param-value>/isignature/Service.jsp</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>SetCharacterEncoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
对应java方法
package com.horizon.filter.encoding;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
public class SetCharacterEncodingFilter implements Filter {
protected String encoding;
protected boolean ignore;
// 排除不进行统一编码的页面
protected String excludedPages;
public SetCharacterEncodingFilter() {
this.encoding = null;
this.ignore = true;
this.excludedPages = "";
}
public void init(FilterConfig filterConfig) throws ServletException {
this.encoding = filterConfig.getInitParameter("encoding");
String value = filterConfig.getInitParameter("ignore");
this.excludedPages = filterConfig.getInitParameter("excludedPages");
if (value == null)
this.ignore = true;
else if (value.equalsIgnoreCase("true"))
this.ignore = true;
else if (value.equalsIgnoreCase("yes"))
this.ignore = true;
else
this.ignore = false;
}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
if ((this.ignore) || (request.getCharacterEncoding() == null)) {
if(excludedPages.indexOf(((HttpServletRequest)request).getServletPath()) == -1) {
String encoding = selectEncoding(request);
if (encoding != null) {
request.setCharacterEncoding(encoding);
}
}
}
chain.doFilter(request, response);
}
public void destroy() {
this.encoding = null;
}
protected String selectEncoding(ServletRequest request) {
return this.encoding;
}
}