GB2312、GBK、UTF-16、UTF-8编码比较
对于中文字符,使用GB2312、GBK、UTF-16、UTF-8均能对其进行处理。但是GBK的范围更大,他能处理所有汉字字符,所以讲GB2312与GBK进行对比,应该选择GBK。UTF-16与UTF-8都是处理Unicode编码,他们的编码规则不太相同。相对来说,UTF-16的编码效率较高,从字符到字节的相互转换更加简单,进行字符串操作也更好,它适合在本地和内存之间使用,但是它不适合在网络之间传输,因为网络传输容易损坏字节流,一旦字节流损坏就很难恢复,所以相比较而言URF-8更适合网络传输,UTF-8对ASCII字符采用单字节存储,另外单个字符损坏也不会影响后面的其他字符,在编码效率上结余GBL和UTF-16之间,所以UTF-8在编码效率和编码安全性上做了平衡,是理想的中文编码方式。
URI解码
用户提交一个URL,在这个URL中可能存在中文,因此需要编码。以下介绍URL具体组成部分
浏览器对PathInfo和QueryString的编码是不一样的,不同的浏览器对PathInfo的编码也可能不一样。tomcat对于URL中URI进行解码的字符集是在connector的
GET方式提交的HTTP请求中的QueryString解码
不管是以Get方式的HTTP请求的QueryString还是以POST方式HTTP请求的表单参数都是作为Parameters保存的,都通过request.getParameter获取参数值,对他们的解码都是在request.parameter方法第一次被调用时进行的。
request.getParameter方法被调用时将会调用org.apache.catalina.connector.Request的parseParameters方法。这个方法将会对GET和POST方式传递的参数进行解码,但是他们的解码字符集有可能不一样,对POST表单的解码将在后面介绍。QueryString的解码字符集是通过HTTP的header传到服务端的,QueryString的解码字符集要么是Header中的ContentType定义的charset,要么是默认的ISO-8859-1,要使用ContentType中的定义的编码,就要将Connector的
POST方式提交的HTTP请求中的表单字段的解码
POST表单的参数传递方式与QueryString不同,它是通过HTTP的Body传递到服务端的,当我们页面上单击提交按钮时浏览器首先将根据ContentType的Charset编码格式对在表单中填入的参数进行编码,然后提交到服务器端,在服务器端同样也是用ContentType中的字符集进行解码的。而且这个字符集我们也可以自己设置,通过request.setCharacterEncoding(charset)来设置。
HTTP Header的编解码
当客户端发起一个HTTP请求时,除上面的URL外还可能会在Header中传递其他参数,如Cookie、redirectPath等,这些用户设置的值很可能也会存在编码问题,对header的解码实在调用request.getHeader时进行的,如果请求的header项没有解码则调用MessageBytes的toSring方法,这个方法对从byte到char的转化使用的默认编码ISO-8859-1,而我们不能设置Header的其他解码格式,所以如果你设置的heaer中有非ASCII字符,解码肯定会有乱码。
HTTP Response Body的编解码
当用户请求的资源已经成功获取后,这些内容将通过response返回给客户端浏览器,这个过程要先经过编码,再到浏览器进行解码,编解码字符节可以通过response.setCharacterEncoding来设置,它将覆盖request.setgetCharacterEncoding的值,并且通过Header的Content-type返回给客户端,如果返回的Http Header中Content-type没有设置Charset,那么浏览器将根据HTML的<meta HTTP-equiv=”content=”text/html; charset=GBK”/>中的charset来解码。如果也没有定义,则浏览器使用默认的编码来解码。