网管联盟 | 网管论坛 | 网管u家 | 网管博客 | 网管软件 | 网管求职 | 小游戏 | 网管搜索 | 网管原创 | 网管聚合 | 网管读摘 | 网管焦点 | 世界素材 | 会员投稿 | 会员中心 
中国网管联盟
Windows Linux Cisco 网络技术 数据库 黑客攻防 DotNet Java PHP 认证 新闻资讯 服务器 存储资讯 网络设备 网管学堂 技术专题 焦点 网吧频道
 当前位置: > bitsCN.com > JAVA > J2EE > Servlet/Jsp > 剖析JSP和Servlet对中文的处理(2)  

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

2002-09-18  作者:BitsCN整理  来源:中国网管联盟  点评 投稿 收藏


  奇怪了!为什么把设成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时的情况,肯定是不正确的。
中国网管联盟bitsCN.com

  
  当输出对象是数据库时
  
  输出到数据库时,原理与输出到浏览器也是一样的。我们只以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中指定的字符集还原成客户端能识别的字节流,通俗地说,就是“字符串变量是基于字符集的”。 网管网www.bitscn.com
  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字符; 网管论坛bbs_bitsCN_com
  
  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): 中国网管论坛bbs.bitsCN.com
   
  图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,输入如下命令:
网管bitscn_com

  
  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支持该方法。
网管联盟bitsCN_com

  
  
  
  
  
  

TAGs   处理   中文   剖析   字符串   字符集   客户端   数据库   ISO8859-1      
 上一篇:我认为JSP有问题(上)   下一篇:剖析JSP和Servlet对中文的处理(1)
相关文章列表
剖析JSP和Servlet对中文的处理(2) 评论:
loading.. 评论加载中…
评论:请自觉遵守互联网相关政策法规,评论不得超过250字。

验证码: 注册用户
本类热门排行:
1.配置Eclpise+tomcat与实现JSP部署
2.JSP中include指令和include行为区别
3.在JSP中如何实现MD5加密
4.JSP程序流程图
5.ServletContext与ServletConfig分析
6.让FCKeditor在JSP和JSF项目中跑起来
7.JSP报表打印的一种简单解决方案
8.JSP常用语法
9.实现jsp页面得分页显示功能方案
10.Servlet 容器的工作原理 ( 四 )
最新推荐文章:
1.Java程序员必看--扩展鼠标右键菜单功能
2.JSP、Java实现选择框多级连动
3.JSP操作用以提高数据库访问效率
4.详细解析JSP中九个隐含对象
5.jsp/servlet取参数乱码问题分析
6.择JSF而不选Struts的十大理由
7.关于jsp的定时实现过程
8.一个实用的东西——JSP分页
9.缓冲技术提高JSP程序的性能和稳定性
10.jsp超级链接实现"目标另存为"功能
网管论坛交流:
·不疯魔不成活
·令你大开眼界的真正标准化机房,已整理重
·为赈灾,女孩舍身拍“裸照”
·Windows Server 2003服务器群集创建和配
·exchange2k3全套官方资料
·双儿一周岁了。。。特殊的礼物来啦。。
·存储备份技术版块守则
·无盘技术交流区守则
·DOS命令基础大全之命令详解<作者吐血
·Windows XP 操作系统默认设置需要注意的