JSP/Serverlet 中的编码问题(转)

(1)jsp页面中的pageEncoding:指定jsp编写时所用的编码(源文件编码)

(2)jsp页面中的contentType:它指定的是jsp页面最终在客户端浏览器呈现时所见到的内容的编码。

(3)Jsp从源文件到最终用户看到的html文件,会大致经历如下阶段:

① 所编写的源文件的保存, 由于计算机只能保存二进制形式的内容,而我们所写的都是字符串形式的内容,所以这里进行的第一个阶段即是由字符串到字节的编码过程,这个阶段所采用的就是PageEncoding所指定的编码, 如这时指定的是GBK, 则会将一个汉字拆分成二个字节来保存,如果用的是utf-8则会用三个字节来保存。[jsp页面的pageEncoding的默认值是iso8859-1]

② 本阶段是从.jsp文件中读取二进制信息并翻译成.java文件的过程(这一过程由服务器如tomcat在运行
时时完成), 服务器读取出二进制信息(字节), 然后用其保存时所使用的字符编码来重新进行解码,将其还原成原始字串. 这时系统再使用UTF-8对字符串重新进行编码,并将其得到的字节信息写入到x.java文件中(这与src中的.java文件不同,src中的.java文件采用的是平台使用的字符集,而这里统一都用UTF-8)。

③ 这一阶段是完成从.java文件到源文件.class文件的编译过程,这时系统会从.java文件中读出字节数
据,然后直接将其写入.class文件中,所用编码方式仍为UTF-8。

④ 本阶段是由tomcat从class文件中读取二进制信息,然后通过网络发送出去, 具体用来实施这个工作的对象是response对象。而这个对象在发送数据前先要将数据根据UTF-8还原成原始字串,然后再按
contentType 所指定的编码(如果没设则与pageEncoding一样)将字串编码为字节流,然后再通过网
络发送出去。

⑤ 这阶段的主要工作将由浏览器来完成. 此阶段浏览器接收到字节流后,要负责将其解码为字符串,而解码所使用的字符码式仍为contentType所指定的编码方式。

至此用户就可以看到我们原先写的字符串了。

其实上面几步中前面几步都没可以省略不看,我们关键要看的是最后两步(即网络发送前的编码和到达浏览器后的解码过程)来看下面几种情况:

a) <%@ page pageEncoding="GBK" contentType="text/html; charset=iso8859-1"%>

假设页面中有:<h1>中</h1>当走到第4步时,服务器会读取出字节并正确还原成字符串"<h1>中</h1>", 这时response在发送前需要先将其变为字节序列,所使用的编码标准就是iso8859-1(由charset指定), 它会将一个英文解析为一个字节,将一个中文也解析为一个字节,这样数据在发送前就已经丢失了,所以到达浏览器时也必然为少了一个字节了。故我们会看到?输出。

b) <%@ page pageEncoding="GBK" contentType="text/html; charset=utf-8"%>

假设页面中有: <h1>中</h1>发送前会将所有中文字符编码为三个字节、英文字母和数字仍为1个字节,然后送出,到浏览器后,再用同样的字符编码将字节解码为字符串(中文三个一组),所以数据不会丢失,不会出现乱码。编码本身提供了一套标准来识别某个字节是否是中文字符的开始部分。

c) <%@ page pageEncoding="utf-8" contentType="text/html; charset= GBK"%>

假设页面中有:<h1>中</h1>发送前会将所有中文字符编码为二个字节、英文字母和数字仍为1个字节,然后送出,到浏览器后,再用同样的字符编码将字节解码为字符串(中文二个一组),所以数据不会丢失,不会出现乱码。

(4)Jsp向servlet提交数据时的编码问题:

前面部分都一致,关键问题是字节流到达服务器后的解码(字节->字符)过程, 与页面不同的是它不采用contentType指定的字符编码方式来解码字节,而是采用服务器(tomcat默认值为iso8859-1)来解析,这样一个字节就被还原成了一个字符, 这时如果我们的jsp指定的contentType是UTF-8, 就会出现本来是一个字符的三个字节被分别解析成了三个字符,所以乱码也就产生了。

我们可以通过手工的方式来设置字节的解码方式,具体做法是在用request的getParameter方法前调用request的 setCharacterEncoding(“解码方式”); 将编码和解码的码式设为一致,如前面contentType设置为utf-8, 此处也就设置为utf-8, 这样信息就能顺利还原了。

注:在tomcat中对于get方式提交的数据不论request的setCharacterEncoding设置的是何种字符编码方式,服务器均采用ISO8859-1方式对其进行解码,所以我们要想得到正确数据,就可以通过:

String str =  request.getParameter("xxx");
str =  new  String (str.getBytes("ISO8859-1","contentType指定的编码");

这样先将数据还原,然后再用发送时的字符集来进行解码,这样就可将数据还原了。

原文地址:https://www.cnblogs.com/chonghaojie/p/5553560.html