没有眼泪
Don't Cry!
posts - 13,comments - 44,trackbacks - 0
在javaweb开发过程中get和post乱码是一个老生常谈的话题了,相信人人都遇到过。网上的文章也很多,但往往是看的越多就越糊涂,有些东西只有自己了然于心才能真正地明白。下面就写一篇文章,就乱码产生的过程分析一下。
为什么会产生乱码?

1.   为什么会产生乱码?

因为浏览器不允许提交非ASCII字符,如果提交了非ASCII,则浏览器自动对其进行编码,将它们转换为ASCII字符。根据浏览器的不同,转换时使用的编码也不同,比如有些浏览器会使用utf-8进行编码,而有些会使用gbk进行编码。

2.   浏览器为什么不允许提交非ASCII字符?

以下是我个人观点,仅供参考。

因为浏览器和服务器通信,传输的都是字节。而我们在页面提交的都是字符,所以浏览器底层就有一个将字符转换为字节的过程,这个过程涉及到编码,浏览器到底是用utf-8gbk还是iso-8859-1将字符转换为字节呢?我想应该是iso-8859-1,因为这是西欧默认使用的编码。何况,也没有任何理由使用前两种编码格式。但是iso-8859-1编码是不能识别中文以及其他非ASCII字符的,所以如果字符中存在这类字符,那么将字符转换为字节的过程中势必会产生乱码。为了避免这种情况的发生,浏览器自动对非ASCII字符进行了编码,将这类字符转换为ASCII字符,这样就能避免乱码问题。

3.   GETPOST提交表单,分别根据什么对非ASCII字符进行编码?

GET

情况比较复杂,不同浏览器也不一样,有的使用gbk,有的使用utf-8不好一概而论。

POST

浏览器会根据网页编码对表单中的数据编码。比如我们在jsp页面第一行所写的:<%@page contentType="text/html;charset=UTF-8"%>。那么这个网页响应给客户端后使用的就是utf-8编码,那么post时使用的也是这个编码。

编码后的格式可以参考java中的URLEncoder.encode方法编码的结果。

4.   服务器底层如何处理提交的数据。

上面2已经提到,客户端和服务器端传输的是字节,那么服务器端接收到的原始数据就是字节。但是我们的程序通常需要从服务器获取字符,而不是字节,所以服务器端必须将字节转换为字符。这里也涉及编码,服务器采取什么编码方式将字节转换为字符?我想也是iso-8859-1,这样和客户端的编码方式一致,不会产生乱码,相当于一个还原字符的过程。这里有个问题,比如客户端发送:name=%D6%D0%B9%FA,那么服务器端还原后也是:name=%D6%D0%B9%FA。那么我们使用request.getParameter(“name”)如何能得到正确的值呢?难道要我们自己再进行转换?答案是:NO。根据Servlet规范,Servlet中获取数据的方法会按照指定的字符集解码。指定的字符集是什么?默认是iso-8859-1。正是因为使用了iso-8859-1解码我们发送的参数,导致了乱码的产生,这里才是产生乱码的源头。具体解码的过程可以看看javaURLDecode.decode方法。既然知道了产生乱码的原因是因为服务器默认使用iso-8859-1解码,那我们就得想办法更改服务器使用的解码编码。好在服务器已经提供给我们修改的方式了,我们可以在服务器中进行配置,比如Tomcat可以在server.xml中进行配置,比如:URIEncoding="GBK"这样服务器就会使用gbk编码解码,这种方式主要针对GET提交的数据,对于POST更常用的是request.setCharacterEncoding(String charset)设置解码编码。

5.   为了避免乱码,客户端应该如何做?

GET

对于含有非ASCII字符的URL自己进行编码,比如使用javascript中的方法进行编码。这样就不需要浏览器为我们编码了,从而解决了浏览器编码的不确定性。

POST

只要正确设置网页编码即可。

posted @ 2013-07-27 16:56 zhangchao 阅读(4375) | 评论 (2)编辑 收藏
     摘要: 工作中经常遇到java编码问题,由于缺乏研究,总是无法给出确切的答案,这个周末在网上查了一些资料,在此做些汇总。     问题一:在java中读取文件时应该采用什么编码? Java读取文件的方式总体可以分为两类:按字节读取和按字符读取。按字节读取就是采用InputStream.read()方法来读取字节,然后保存到一个byte[]数组中,最后经常用new Stri...  阅读全文
posted @ 2011-05-26 10:35 zhangchao 阅读(40426) | 评论 (19)编辑 收藏