servlet的编码原理

转自:http://www.cnblogs.com/dvking/archive/2012/01/02/2368703.html

编码问题:

在介绍编码问题前,先介绍一下java平台(JVM)上的编码转化情况。首先要说明的一点,在JVM中,即java平台上,运行的程序一定都是Unicode编码方式的。对于代码中的字符串常量,根据代码页的设置,转化为Unicode编码。对于输入,在输入进程序中JVM已经把输入的内容根据原先输入的编码方式转化为Unicode。若未指明,则是用系统默认的编码方式去转化为Unicode。对于输出,则是把Unicode编码按指定的编码方式输出,未指明则按系统默认编码输出。

编码问题出现的位置:

         1.web浏览器发送请求 对于此请求中的参数要进行编码。区分get方式和post方式。

                Get方式:由于get方式下的参数是放置于消息头中,而消息头是由浏览器根据自身特性去进行编码的,一般是UTF-8,但也有的浏览器不是。

                   Post方式:根据HTML页面Content-Type属性,如:Content-Type设置为“text/html;charset=”gb2312””则浏览器按gb2312去编码。

         2.服务器接收到请求,这里假设服务器为Tomcat且运行的是servlet(jsp——jsp运行时仍编译成servlet,所以这里直接用servlet来表示)。

         对于Post方式的请求,servlet默认会用ISO-8859-1将消息体中的参数转化为Unicode。如果是汉字,这是很不合理的,因为ISO-8859-1只有一个字节,是不支持汉字。所以在对HttpServletRequest对象利用getParameter()方法获取参数值时,必须先要用setCharacterEncoding()方法设置其解码方式,如req.setCharacterEncoding(“UTF-8”),这样调用的getParameter()方法会按UTF-8的方式把参数转化为Unicode。

         Get方式的请求,首先要说明的,get方式下的请求,上述用setCharacterEncoding()方法设置解码方式是行不通的。其原因在于:get方式的请求参数放在消息头中,而消息头是在web容器的任何servlet接受前就已经先被web容器解释了,因为只有这样web容器才可以知道去具体调用哪个servlet。至于web容器如何解释消息的,serlvet标准中并没用明确规定,所以有的web容器按ISO-8859-1去解释为Unicode,有的则是按系统默认编码。

所以对于get方式下用setCharacterEncoding()方法设置解码方式是无用的。而相反,对于post方式,消息体一般是在第一次调用HttpServletRequest对象的getParameter()方法时,才开始实际处理。

         所以由于get方式解码的未知性,一般所带参数都是不带中文的,若要带中文,则用post方式比较方便。但若要追求高效,非要用get方式时,则可以使用String类中getBytes()方法转为字节数,再用String(byte[],”编码”)构造函数去获取字符串。

         3.服务器输出响应

         服务器输出响应比较简单。由于servlet程序中所有字符都是统一码Unicode,所以输出时,按照response对象设定的Content-type中的字符集,servlet会自动根据其字符集将Unicode编码转为指定字符集输出。仍要说明的一定是,对于servlet程序中的常量字符串,则是按照代码页将其转化为Unicode。

编码问题的关键:

         需要把接收的数据转化为Unicode编码,再由java处理;输出的数据由Unicode编码转化为指定编码后输出。

         具体来说,对于接收的数据,web容器一般按默认的ISO-8859-1去解码。对于汉字,需要用GBK等去解码,再转换成Unicode。但对于URL后的参数无法设置解码方式,故一般不要用汉字。对于Post方式的消息体,可以用setCharacterEncoding方式去设置解码方式。

         但JavaScript等脚本语言中,没用对编码方式转换成Unicode,而是直接保存、返回的。所以写代码过程中,若有汉字,一定要注意使代码页和HTML中的字符集相同。代码页的作用是:能够对程序中的常量字符串正确的解码。

原文地址:https://www.cnblogs.com/renwei/p/4262186.html