WebX中关于编码的问题

web中的编码一直是个让人头疼的问题,上次二面的时候就被面试官问的比较惨,看似了解也一直在用着,却一直没搞清楚过里面的道道。

今天在学习WebX的时候又碰到编码问题了,好记性不如烂笔头,还是做一下笔记,总结沉淀一下。

常见的编码:

UTF-8

涵盖了unicode中的所有字符。然而用UTF-8来编码中文为主的页面时,每个中文会占用3个字节。建议以非中文为主的页面采用UTF-8编码。

GB18030
中文国际标准,和UTF-8一样,涵盖了unicode中的所有字符。用GB18030来编码中文为主的页面时有一定优势,因为绝大多数常用中文仅占用2个字节,比UTF-8短1/3 。然而GB18030在非中文的操作系统中,有可能不能识别,其通用性 不如UTF-8好。因此仅建议以中文为主的页面采用GB18030编码。

GBK
严格说,GBK不是全能编码(例如对很多西欧字符就支持不好),也不是国际标准。但它支持的字符数量接近于GB18030。

    HTTP请求主要有2种:GET和POST。GET一般用于获取/查询资源信息,而POST一般用于更新资源信息。

  参考:浅谈HTTP中Get与Post的区别

           http://www.cnblogs.com/hyddd/archive/2009/03/31/1426026.html

Charset全称Character Encoding或字符集编码。Charset是将字符(characters)转换成字节(bytes)或者将字节转换成字符的算法。Java内部采用unicode来表示一个字符。将unicode字符转换成字节的过程,称为“编码”;将字节恢复成unicode字符的过程,称为“解码”。
浏览器发送给WEB应用的request参数,是以字节流的方式来表示的。Request参数必须经过解码才能被Java程序所解读。用来解码request参数的charset被 称为“输入字符集编码(Input Charset)”;
WEB应用返回给浏览器的response响应内容必须编码成字节流,才能被浏览器或客户端解读。用来编码response内容的charset被称为“输出字符集编码( Output Charset)”。
一般情况下,input charset和output charset是相同的。因为浏览器发送表单数据时,总是采用当前页面的charset来编码的。例如,有一个表单页面,它的“contentType=text/html; charset=GBK”,那么用户填完全表单并提交时,浏览器会以GBK来编码用户所输入的表单数据。如果input charset和output charset不相同,服务器就不能正确解码浏览器根据output charset所发回给WEB应用的表单数据。

在Servlet/JSP编程的时候经常会出现乱码,通过调用setCharacterEncoding(charset)来设置输入编码方式,如果不设置,则默认以ISO-8859-1来解码参数(一般只影响POST请求参数的解码)。


解析GET请求的参数

GET请求是最简单的请求方式。它的参数以URL编码的方式包含在URL中。当你在浏览器地址栏中敲入“http://localhost:8081/user/login.htm?name=%E5%90%8D%E5%AD%97&password=password”这样一个址址的时候,浏览器就会向localhost:8081服务器出如下HTTP请求:

<span style="font-family:SimSun;font-size:14px;">GET /user/login.htm?name=%E5%90%8D%E5%AD%97&password=password HTTP/1.1
Host: localhost:8081</span>
GET请求中的参数是以application/x-www-form-urlencoded方式和特定的charset编码的。假如用来编码URL参数的charset与应用的默认charset不同,那么你必须通过特殊的参数来指定charset(参见第 7.2 节 “<set-locale> -设置locale区域和charset字符集编码”)
<span style="font-family:SimSun;font-size:14px;">GET /user/login.htm?_input_charset=UTF-8&name=%E5%90%8D%E5%AD%97&password=password HTTP/1.1</span>

可是,上面的请求在不同的Servlet引擎中,会产生不确定的结果。这是怎么回事呢?

原来,尽管<set-locale>会调用request.setCharacterEncoding(charset)这个方法来设置input charset编码,然而根据Servlet API的规范,这个设定只能对request content生效,而不对URL生效。换句话说,request.setCharacterEncoding(charset)方法只能用来解析POST请求的参数,而不是GET请求的参数。

那么,应该怎样处理GET请求的参数呢?根据URL规范,URL中非US-ASCII的字符必须进行基于UTF-8的URL编码。然而实际上,从浏览器到服务器,没有人完全遵守这些规范,于是便造成了一些混乱。目前应用服务器端,我们所遇到的,有下面几种不同的解码方案:


综上所述,所有的应用服务器对于POST请求的参数的处理方法是没有差别的,然而对于GET请求的参数处理方法各有不同。
如果不加任何特别的设置,Tomcat最新版是以ISO-8859-1来解码GET请求的参数,而Jetty却是以UTF-8来解码的。因此,无论你以哪一种charset来编码GET请求的参数,都不可能在所有服务器上取得相同的结果 ── 除非修改服务器的配置,但这是一件既麻烦又容易出错的事情。为了使应用程序对服务器的配置依赖较少,且可以灵活地处理GET请求的解码,<parser>对GET请求进行了手工解码,从而解决了应用服务器解码的不确定性。
<parser>完全解决了上面的问题。依据默认值,<parser>会以<set-locale>中设定的input charset为准,来解码所有类型的请求,包括GET和POST请求,以及multipart/form-data(上传文件)类型的请求。











评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值