乱码的原因:
编码不一致导致乱码。(原因很简单是不是)
解决乱码:
规范、统一编码。(这不废话嘛,赶紧入正题)
好了,我们已经知道产生乱码的原因,更重要的我们已经知道解决乱码问题的思路,那么,
有了思路就有了切入点(这里只讨论jsp/serlet,原理是通用的)。
简化的B/S请求(不让上传本地图片,只好先上传到微博,用画图画的。。。)
测试环境:eclipse+weblogic+jdk1.5.22
web.xml:
<context-param> <param-name>weblogic.httpd.inputCharset./*</param-name> <param-value>GBK</param-value> </context-param>
设置weblogic http-request全局编码,即对所有request请求都设置request.setCharacterEncoding("GBK")。
test.jsp:
<%@ page language="java" pageEncoding="UTF-8" contentType="text/html; charset=GB18030"%>
...
...
...
<html:form action="/csi/bx/op" method="post">
姓名:<input name="personName" />
...
...
JSP文件头设置pageEncoding和contentType指令。
在姓名文本框中输入:“编码”这两个汉字,使用TCPMON抓包:
request报文:
POST /csi/bx/op.do HTTP/1.1
Accept: image/jpeg, application/x-ms-application, image/gif, application/xaml+xml, image/pjpeg, application/x-ms-xbap, application/msword, application/vnd.ms-excel, application/vnd.ms-powerpoint, */*
Referer: http://localhost:7001/csi/bx/a.jsp
Accept-Language: zh-CN
User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0)
Content-Type: application/x-www-form-urlencoded
Accept-Encoding: gzip, deflate
Host: 127.0.0.1:7001
Content-Length: 95
Connection: Keep-Alive
Cache-Control: no-cache
Cookie: JZZZGSESSION=7PJ3PhjSc723MvJ1k4YZVv0KJY79tySnTCtX1Gh2Qf7VKWmVdyh7!-528097381
personId=&identityNo=&personName=%B1%E0%C2%EB&b_sybxpayment=%B2%E9%D1%AF&methodName=sybxPayment
看最后一行,汉字 “编码” 已经被url encoding成%B1%E0%C2%EB,使用的编码是GB18030,也就是contentType设置的编码。
response报文:
HTTP/1.1 200 OK
Date: Fri, 27 Apr 2012 09:25:59 GMT
Content-Length: 2578
Content-Type: text/html; charset=GB18030
X-Powered-By: Servlet/2.5 JSP/2.1
response返回报文使用的编码是GB18030,也是contentType设置的编码。
不信?那我们把test.jsp文件的contentType换成UTF-8,在姓名文本框中一样输入汉字”编码“,继续抓包:
request报文:
POST /csi/bx/op.do;JZZZGSESSION=nJMqPhkGJWHwLMqHTX7WWMKvThZv45JsdPXwQ7TmW8TycpZLpmT1!-528097381 HTTP/1.1
Accept: image/jpeg, application/x-ms-application, image/gif, application/xaml+xml, image/pjpeg, application/x-ms-xbap, application/msword, application/vnd.ms-excel, application/vnd.ms-powerpoint, */*
Referer: http://localhost:7001/csi/bx/a.jsp
Accept-Language: zh-CN
User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0)
Content-Type: application/x-www-form-urlencoded
Accept-Encoding: gzip, deflate
Host: 127.0.0.1:7001
Content-Length: 107
Connection: Keep-Alive
Cache-Control: no-cache
Cookie: JZZZGSESSION=nJMqPhkGJWHwLMqHTX7WWMKvThZv45JsdPXwQ7TmW8TycpZLpmT1!-528097381
personId=&identityNo=&personName=%E7%BC%96%E7%A0%81&b_sybxpayment=%E6%9F%A5%E8%AF%A2&methodName=sybxPayment
很显然,汉字”编码“被编码成%E7%BC%96%E7%A0%81,使用UTF-8编码,每个汉字占3个字节。
乱码产生了:由于weblogic容器使用的编码为GBK,上面有描述,即requset.setCharacterEncoding("GBK"),
而客户端request报文是以UTF-8进行编码,那么,在request.getParameter得到的就是乱码。
response报文:
HTTP/1.1 200 OK
Date: Fri, 27 Apr 2012 09:19:12 GMT
Content-Length: 2580
Content-Type: text/html; charset=UTF-8
X-Powered-By: Servlet/2.5 JSP/2.1
response返回报文使用的编码已经是UTF-8了(这次信了吧)。
由此,可以看出contentType会影响url-encoding(URL编码-简单理解就将汉字表示成以%开头的字符串,每个字符串占1个字节),
同时会影响response报文的编码,如果在代码中有response.setCharacterEncoding(charset),
response报文的编码将以代码的为主。
接下来是pageEncoding,顾名思义,pageEncoding就是页面编码,通俗点就是文件编码或JSP文件编码,
文件是什么编码,pageEncoding写什么编码,这个很简单了吧。
但是,我们通常会遇到一种情况,如果在浏览器直接访问test.jsp,页面正常无乱码,当我们提交action,
服务器重新跳转到test.jsp,页面上出现了乱码,原因是response报文的编码和pageEncoding编码不兼容导致的。
JSP:
<%@ page language="java" pageEncoding="GB2312"%>
页面的编码是GB2312。
response报文:
HTTP/1.1 200 OK
Date: Fri, 27 Apr 2012 09:25:59 GMT
Content-Length: 2578
Content-Type: text/html; charset=UTF-8
X-Powered-By: Servlet/2.5 JSP/2.1
报文的编码是UTF-8,那么JSP页面就会出现乱码。
总结:
1、pageEncoding=文件编码
2、contentType=request.setCharacterEncoding(一般在代码或过滤器中会设置)
3、pageEncoding的编码要 兼容 contentType或response.setCharacterEncoding设置的编码,
比如UTF-8兼容GB2312,但GB2312不兼容UTF-8
”=“表示一致