5. 乱码问题

1 乱码产生原因

  1. 浏览器发送Http请求时,会对请求进行编码,接收Http响应时,会对响应进行解码
  2. 而服务器接收到Http请求,和产生Http响应时,也会进行解码和编码
  3. 当浏览器的编码、解码使用的字符集,与服务器解码、编码所使用的字符集不相符时,就会产生乱码

2 常用软件默认字符集查看

  1. eclipse:Windows–General–Workspace
  2. windows:chcp命令,936表示GBK

3 请求中的乱码

3.1 浏览器对请求的编码方式
  1. 请求头:iso-8859-1
  2. 请求行、体:默认utf-8
<!--可以对form设置accept-charset,从而改变浏览器对请求行、体的编码方式-->
<form action="reqdecode"  method="get" accept-charset="gbk">
3.2 服务器对请求的解码方式
  1. 请求头:tomcat7默认iso-8859-1,tomcat8为utf-8,无法修改
  2. 请求体:tomcat7,默认iso-8859-1
//修改请求体编码
req.setCharacterEncoding("utf-8");
  1. 请求行:tomcat7,默认iso-8859-1,例如url"http://localhost:8080/测试?网络=编程"
    1. pathinfo(“测试”)编码修改
    <Connector port="8080" protocol="HTTP/1.1"
                   connectionTimeout="20000"
                   redirectPort="8443" 
                   URIEncoding="UTF-8" />
    
    1. queryParameter(“网络=编程”)编码修改,有优先级
      1. URIEncoding=“UTF-8”
      2. useBodyEncodingForURI="true"时,使用体的编码
3.3 GET请求与POST请求乱码处理
3.3.1 处理方案不同原因
  1. 因为get请求的表单数据在queryParameter中,而post请求的表单数据在请求体里,修改服务器对他们的解码方式的方案,是不同的,因此对于get与post请求的乱码问题有不同的处理方案
3.3.2 GET请求乱码解决方案
  1. 方案一
String value = request.getParameter("name");
//对于GET请求,相当于浏览器按utf-8编码,tomcat按iso-8859-1解码,因此乱码
//重新将乱码按iso-8859-1编码,再使用utf-8解码
value = new String(value.getBytes("iso-8859-1"), "utf-8");
System.out.println(value);
  1. 方案二
<!--修改server.xml,使用请求体的解码方式,对queryParameter进行解码-->
<Connector port="8080" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443" 
               useBodyEncodingForURI="true" />
//设置请求体的解码方式为utf-8,而queryParameter与其相同,即也使用了utf-8
req.setCharacterEncoding("utf-8");
  1. 方案三
<Connector port="8080" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443" 
               URIEncoding="UTF-8" />
3.3.3 POST请求乱码解决方案
req.setCharacterEncoding("utf-8");

4 响应中的乱码

4.1 浏览器对响应解码方式
  1. 响应头、行:iso-8859-1
  2. 响应体:默认 gbk
  3. 可以通过修改响应头中的Content-Type,从而改变浏览器对响应的解码方式
resp.setContentType("text/html;charset=utf-8");
4.2 服务器对响应的编码方式
  1. iso-8859-1
  2. 可以通过修改Content-Type,从而改变tomcat对响应体的编码方式
//1. Content-Type的属性值,既可以修改tomcat的编码方式,也可以修改浏览器的解码方式,所以charset中的值,设置为utf-8还是gbk,其实都可以将汉字正确显式
resp.setContentType("text/html;charset=utf-8");
  1. 可以通过setCharacterEncoding方法,修改响应体中的编码方式
//1. 要求tomcat以gbk对响应体进行编码,这种方法没有修改浏览器的解码方式,所以如果浏览器默认为gbk解码时,此处必须让Tomcat以gbk编码,最后页面中汉字才能正确显式
resp.setCharacterEncoding("gbk");
4.3 响应乱码解决方案
  1. 方案一
OutputStream os = response.getOutputStream();
//直接以字节写入响应体中,tomcat不会对字节进行编码,浏览器按默认的字符集GBK进行解码,所以不再出现乱码
os.write("吴思含".getBytes("GBK"));
  1. 方案二
PrintWriter out = response.getWriter();
String data = "博客";
//因为tomcat默认使用iso-8859-1对http数据包进行编码,而浏览器会按操作系统字符集GBK进行解码,所以预先按GBK进行编码,再按iso-8859-1解码,这样解到浏览器时正好是GBK,可以正常显示
//先对字符串data按GBK编码,然后按iso-8859-1解码,形成乱码A,之后tomcat会按默认的iso-8859-1对A进行编码,最后浏览器按GBK进行解码,相当于再次得到了正确的data字符串
out.println(new String(data.getBytes("GBK"),"iso-8859-1"));
  1. 方案三
//对头中汉字无效
response.setCharacterEncoding("gbk");
  1. 方案四
//注意对头中汉字无效
//必须写在获取流上面,charset值设为任何支持中文的字符集都行
response.setContentType("text/html;charset=gbk");
PrintWriter out = response.getWriter();
String data = "博客";
out.println(data);

5 最佳实践

  1. servlet
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
  1. server.xml
<Connector port="8080" protocol="HTTP/1.1"
	               connectionTimeout="20000"
	               redirectPort="8443" 
	               URIEncoding="UTF-8" />
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值