分享
 
 
 

剖析JSP和Servlet对中文的处理(2)

王朝java/jsp·作者佚名  2008-05-19
窄屏简体版  字體: |||超大  

奇怪了!为什么把设成GB2312和ISO8859-1是一个样的,都能正确显示?因为表4、表5中的第2步和第5步互逆,是相互“抵消”的。只不过当指定为ISO8859-1时,要增加第8步操作,殊为不便。

通过表6再看看不指定时的情况。

表6 未指定Jsp-charset时的变化过程

从Servlet源文件到浏览器

前提:Servlet源文件为Java文件,格式是GB2312,且含有“中文”这两个汉字。

如果=GB2312,则=GB2312(见表7)。

表7 Compile-Charset=Servlet-charset=GB2312时的变化过程

如果=ISO8859-1,则=ISO8859-1(见表8)。

表8

Compile-charset=Servlet-charset=ISO8859-1时的变化过程

注意:如果不指定Compile-charset或Servlet-charset,其默认值均为ISO8859-1。

当Compile-charset=Servlet-charset时,第2步和第4步能互逆,“抵消”,显示结果均能正确。读者可试着写一下Compile-charset≠Servlet-charset时的情况,肯定是不正确的。

当输出对象是数据库时

输出到数据库时,原理与输出到浏览器也是一样的。我们只以Servlet为例,JSP的情况请读者自行推导(见表9)。

假设有一个Servlet,它接收来自客户端(IE,简体中文)的汉字字符串,然后把它写入到字符集为ISO8859-1的数据库中,然后再从数据库中取出这个字符串,显示到客户端。

前提:客户端的字符集是GB2312,数据库的字符集是ISO8859-1。解释一下,表中第4、第5步和第15、第16步表示要由编程者来作转换。第4、5两步其实就是一句话:“new String(source.getBytes("ISO8859-1"), DBCharset)”。第15、16两步也是一句话:“new String(source.getBytes(DBCharset), ClientCharset)”。亲爱的读者,你在这样编写代码时,是否想过为什么要这么做呢?

字节流

结论及结束语

行文至此,已可告一段落了。以下给出一个结论,作为结尾。

1.在JSP文件中,要指定contentType。其中,charset的值要与客户端浏览器所用的字符集一样;对于其中的字符串常量,不需做任何处理;对于字符串变量,要求能根据ContentType中指定的字符集还原成客户端能识别的字节流,通俗地说,就是“字符串变量是基于字符集的”。

2.在Servlet中,必须用HttpServletResponse. setContentType()设置charset,且设置成与客户端字符集一致;对于其中的字符串常量,需要在Javac编译时指定encoding,这个encoding必须与编写源文件平台的字符集一样。一般说来都是GB2312或GBK;对于字符串变量,与JSP一样。必须“是基于字符集的”。

终点又回到了起点,对于编程者而言,几乎是什么影响都没有。因为我们早就被告之要这么做了。

案例分析

案例:某用户在英文Windows上,安装了外挂的中文平台,操作系统的字符集是“西欧字符”,对应着ISO8859-1字符集,外挂的中文平台是基于Big5码的。当操作者在浏览器(默认编码是ISO8859-1)中输入汉字时,这个汉字用Big5编码(在页面上无法正确显示)。然后,浏览器把数据提交给服务器端。同时,有另一个用户,在中文版的Windows 2000平台上做了同样的事情。服务器端程序需要正确处理来自多种内码的客户端的字符串,以便正确地保存到数据库中。

本案例涉及到多步转换。在第一种客户端上:

1. 在客户端,Big5内码封装成ISO8859-1内码;

2. 把封装后的ISO8859-1字符流传输到Java程序端;

3. Java程序先是用ISO8859-1识别输入流,再用Big5内码来识别夹杂在其中的Big5字符;

4.在Java程序中的字符串已经是Unicode的了,而且它所代表的图形符号与客户端的文字所呈现的图形符号是完全相同的。

在第二种终端上:

1.客户端把GB2312的字符串与其它内容一起以GB2312编码方式传输到服务器端;

2.Java程序先用GB2312内码识别所有输入流,再用GB2312内码识别其中的字符串;

3.Java程序中的Unicode编码的字符串所代表的图形符号与客户端字符的图形符号是完全相同的。

以上是输入逻辑。再看输出逻辑。

有两个与数据库相关的字符集:一是数据库真正的字符集,称为DBCharSet;二是数据库中表现中文的字符集,称为DBChineseCharSet。这一点有些难以理解。请看下述规则:

1. 与中文相关的内容被按照DBChineseCharSet转化成字节流A;

2. 把字节流A和其它非中文的内容加在一起,形成新的字节流B;

3. 数据库以自己的字符集(DBCharSet)存放字节流B的所有内容。

这种思想类似于TCP/IP协议的层层封装。

还是看一看具体的例子吧。以第一种客户端为例(第二种原理是一样的)。假定数据库字符集是ISO8859-1,数据库中中文字符集为GBK(如图4):

图4

图4所示是从客户端接收数据然后写到数据库中的过程。从数据库中读出是其逆过程,请读者自行扩展到各种情况。

下面给出一段Servlet源程序,仅供参考。其功能是模拟客户端输入,然后写入数据库中。请读者自行体会与上文中的例子“testServlet3.Java”的区别。

用“Javac-encoding gb2312 testEncode.Java”编译完成后,执行之。这里之所以用GB2312进行编译,是因为该文件用UltraEdit for Windows在GB2312环境下书写的。结果如下:

SOURCE=4e2d6587

//这是用Javac -encoding gb2312编译的结果

Source_Iso=a4a4a4e5

//显示出来时把前导的“00”丢掉了,实际中应该有

Java_Iso=a4a4a4e5

//同上

Java_Unicode=4e2d6587

//在Unicode中表示“中文”这两个字

DB_Iso=d6d0cec4 //也是在显示时把前导“00”丢掉了

OK,检查一下数据库中是不是正确存放了用GBK表示的“中文”两字。打开SQLPLUS,输入如下命令:

SELECT ASCII(SUBSTR(NAME,1,1)),ASCII(SUBSTR(NAME,2,1)),

ASCII(SUBSTR(NAME,3,1)), ASCII(SUBSTR(NAME,4,1))

FROM TEST_TABLE;

得到的结果如下:“214

208

206

196”,正是十六进制的“D6 D0 CE C4”。

验证成功!

SetCharacterEncoding和getCharacterEncoding

在Servlet/JSP规范中,还有两个很重要的方法:setCharacterEncoding和getCharacterEncoding。这两个方法是在ServletRequest类中定义的。显而易见,就是设置(获取)如何从HTTP输入流中读取字符的字符集的。从上文可以看出,HTTP在网络上传输字符串的方式是先把字符串按照某种字符集编码。然后,把编码后的字符串按ASCII方式传输。

如果这时直接用诸如getParameter()方法读取参数,那么得到的就是经过编码后的字符串,而不是源字符串。通过setCharacterEncoding设置正确的字符集后,可以在读取参数(getParameter)时,直接把经过编码后的字符串还原为源字符串。当然,这时的“源字符串”是用Unicode码表示的。

这两个方法给编程带来了方便,但是却不被某些Servlet/JSP引擎支持,如Tomcat 3.2.x。最新的Tomcat 4.0.1和WebLogic Server 6.1支持该方法。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有