Tomcat 环境下 JSP 中文乱码问题的解决


第 4 期 2011 年湖南 学院学报 Tomcat 环境下 JSP 中文乱码问题的解决 彭 立 (湖南第一师范学院 信息科学与工程系,湖南 长沙 410205) 摘 要:Web 服务器 Tomcat 的中文乱码问题给软件开发人员带来了很大的困惑。为解决这一问题, 可通过分析各种编码方式之间的相互转换,发现中文乱码问题的根源,并对各种出错情况进行分析,找出 解决问题的办法。 关键词:Tomcat;JSP;中文乱码;编码;转换 中图分类号:TP311.1 文献标识码 A 文章编号:1674- 831X(2011)04- 0128- 05 收稿日期:2011- 01- 09 基金项目:湖南第一师范学院院级课题(XYS10N09) 作者简介:彭立(1974—),男,湖南汨罗人,湖南第一师范学院信息科学与工程系讲师。 一、引言 Tomcat 作 为 SUN 公司官方推荐的 JSP 和 Servlet 容器,因其开源、免费、跨平台、配置简单等 特点,得到了广大软件开发人员的喜爱。然而,在 中文操作系统上用 Tomcat 作为 Web 服务器来开 发网站时,会出现中文乱码问题,从而给软件开发 人员带来了很大的困惑。有人对这些问题进行过 分析,但提出的解决办法并不全面也不完全正确。 Tomcat 环境下的中文乱码问题涉及范围很广,本 文旨在解决其中的一类问题:JSP 中文乱码问题。 现将 Tomcat 环境下常见的 JSP 中文乱码问题列举 如下: 问题一:JSP(以下都将 JSP 文件简称为 JSP)本 身包含的中文内容在 IE(以下都将 IE 浏览器简称 为 IE)中显示为乱码。 问题二:表单通过 POST 方式提交给 JSP 的中 文信息在 IE 中显示为乱码。 问题三:表单通过 GET 方式提交给 JSP 的中 文信息在 IE 中显示为乱码。 为了解决 Tomcat 环境下 JSP 中文乱码问题, 有必要先了解该环境下使用的编码方式。 二、Tomcat 的编码方式 解决其他系统软件的中文乱码问题所获得的 经验告诉我们,中文乱码问题往往跟字符的编码 方式有关。编码方式是指字符在计算机内的表现 形式,也就是机内码。在 Tomcat 环境下使用的编码 方式(即字符集)主要有四种:UNICODE、UFT- 8、 GB2312- 80/GBK 和 ISO- 8859- 1。 (一)UNICODE UNICODE 是 Java 内部采用的编码方式,也就 是说,当 Java 程序运行时,数据都会转换为 UNI- CODE 编码保存在内存中。UNICODE 是 DBCS(双 字节字符集),它和任意国家 / 区域使用的本地字 符集之间存在相互映射的关系,通过这样一种映 射关系,它和本地字符集可相互转换。Java 虚拟机 通过操作系统的 Codepage 得知系统采用的字符集 后,就可以使 Java 程序中的数据在 UNICODE 编码 和本地字符编码之间相互转换。 (二)UTF- 8 UTF- 8 以 8 个二进制位为单元对 UNICODE 进行编码,它是网络数据传输以及 Java 类文件所 采用的编码方式。Tomcat 环境下的 JSP 编译成的 Servlet 类 文 件 就 是 以 UTF- 8 编 码 方 式 保 存 的 。 UTF- 8 编码的长度不一,通常西文字符为一个字 2011 年 6 月 第11卷第3期 Jun.2011 Vol.11,No.3 湖南 学院学报 Journal of Hunan First Normal University 128 第 4 期 2011 年 节,而汉字需三个字节。 (三)GB2312- 80/ GBK GB2312- 80/GBK 是汉字的国际码。中文操作系 统中汉字的编码方式都为 GB2312- 80/GBK,而西文 字符的编码方式为 ISO- 8859- 1。GB2312- 80/GBK 是 DBCS,其中 GB2312- 80 只能表示简体字,它包含了 大部分常用的一、二级汉字和 9 区的符号;GBK 是 GB2312- 80 的扩展,既可表示简体字也可表示繁 体 字 ,它 包 含 了 20902 个 汉 字 ,其 编 码 范 围 是 0X8140~0XFEFE,剔除高字节为 0X80 的字位,其 所有字符都可以一对一映射到 UNICODE 2.0。 (四)ISO- 8859- 1 ISO- 8859- 1 是 SBCS(单字节字符集),属于西 欧字符集,它是 Tomcat 默认的编码方式。如无特殊 说明,在编译 JSP 时,Tomcat 会把 JSP 的编码方式 默认看成 ISO- 8859- 1;接收表单输入数据时,Tom- cat 会将数据的编码方式默认看成 ISO- 8859- 1;输 出数据到 IE 时,Tomcat 会默认将数据从 UNICODE 编码转换为 ISO- 8859- 1 编码。 三、编码方式的转换 在 Java 程序运行时,数据以 UNICODE 编码的 形式保存在内存中,Tomcat 根据需要,可将其转换 为 UFT- 8 编码、GB2312- 80 编码或 ISO- 8859- 1 编 码,也可转换回来。Tomcat 环境下的 JSP 从编译到 输出,中间要经过多次编码转换;JSP 接收表单数 据后输出到 IE,期间也涉及到多次编码转换。 (一)UNICODE 和 UFT- 8 之间的转换 UNICODE 和 UFT- 8 之间的转换通常是网络 传输和保存文件的需要。因为 UNICODE 和 UFT- 8 是一一对应的,这两者之间的转换通常不会造成 中文乱码问题。 (二)UNICODE 和 GB2312- 80 之间的转换 GB2312- 80 中所有的字符编码都可转换为对应 的 UNICODE 编码,例如,汉字“你”的 GB2312- 80 编 码为 0XC4E3,对应的 UNICODE 编码为 U4F60。但 是 ,一 个 不 在 GB2312- 80 中 的 字 符 编 码 被 当 作 GB2312- 80 转换为 UNICODE 时,会被转换为一个 特殊编码 UFFFD。反过来,并不是所有的 UNI- CODE 编码都能转换为 GB2312- 80 编码,只有汉字 字 符 的 UNICODE 编码才能被转换为对应的 GB2312- 80 编码,例如,汉字“好”的 UNICODE 编 码为 U597D,对应的 GB2312- 80 编码为 0XBAC3。 不能映射到 GB2312- 80 的 UNICODE 编码转换为 GB2312- 80 编码时,结果为 0X3F,显示出来是“?”。 又如,U00D6 转换为 GB2312- 80 编码为 0X3F。U- NICODE 编码 U00A0~U00FF 之间有 20 个编码在 转换为 GB2312- 80 编码后,显示出来都是乱码字 符 。 再 如 ,U00EC 转 换 为 GB2312- 80 编 码 为 0XA8AC,显示出来为乱码字符“ì”。 (三)UNICODE 和 ISO- 8859- 1 之间的转换 ISO- 8859- 1 中所有的字符编码都可转换为对 应的 UNICODE 编码,转换方法为:在 ISO- 8859- 1 编码的前面加上 0X00。例如字符“A”的 ISO- 8859- 1 编码为 0X41,对应的 UNICODE 编码为 0X0041。一 个不在 ISO- 8859- 1 中的字符编码被转换为 UNI- CODE 编码时,系统并不效验被转换的是否为 ISO- 8859- 1 编码,而是直接按转换方法在编码的 前面加上 0X00。反过来,并不是所有的 UNICODE 编码都能转换为 ISO- 8859- 1 编码。如果 UNICODE 中某个字符编码能被转换为 ISO- 8859- 1 编码,那 么它的高字节必为 0X00,去掉高字节 0X00,保留 低字节,便形成了对应的 ISO- 8859- 1 编码,例如, 字 符 “B” 的 UNICODE 编 码 为 U0042, 对 应 的 ISO- 8859- 1 编码为 0X42。不能映射到 ISO- 8859- 1 的 UNICODE 编码被转换为 ISO- 8859- 1 编码时,结 果为 0X3F,显示出来是“?”,又如汉字“好”的 U- NICODE 编码为 U597D,转换为 ISO- 8859- 1 编码 为 0X3F[1]。 四、Tomcat 中文乱码问题的原因 在 Tomcat 环境下,字符通常要经过“编码方式 A→UNICODE→编码方式 B”这样一个过程,才能 最终输出。 现以汉字“的”为例,看看在 GB2312- 80→UNI- CODE →ISO- 8859- 1 和 ISO- 8859- 1 →UNICODE → GB2312- 80 这两种情况下分别会出现什么问题。 “的”字的 GB2312- 80 编码为 0XB5C4。在第一种情 况下,“的”字的编码方式被看作是 GB2312- 80,转 换成的 UNICODE 编码为 U7684,再由 UNICODE 编 码转换成 ISO- 8859- 1 编码后,结果是 0X3F,显示 出来是一个“?”号。在第二种情况下,“的”字的编 码方式被看作 ISO- 8859- 1,转换成的 UNICODE 编 码 为 U00B5U00C4, 再 由 UNICODE 编 码 转 化 为 彭 立:Tomcat 环境下 JSP 中文乱码问题的解决 129 第 4 期 2011 年湖南 学院学报 GB2312- 80 编码后,结果是0XA6CC0X3F,显示出 来是“μ?”这样两个乱码字符。 可以看出以上两种情况都会造成中文乱码问 题,错误的编码转换过程是 Tomcat 中文乱码问题 的根源。 五、JSP 中文乱码问题的分析和解决 (一)问题一的分析和解决 Tomcat 环境下的 JSP 被 IE 访问时要经过“编 译成 Servlet→载入运行→输出到 IE”这样三个阶 段。现分析一下在每个阶段中编码方式是如何转 换的。 1.编译成 Servlet 当 JSP 被 IE 访问时,Tomcat 会采取以下方式 来判断 JSP 采用了哪种编码方式:首先,它会检查 JSP 中是否有 <%@page pageEncoding=”xx”%> 这 行语句(只有 JSP2.0 才支持这种的语句),如果有, 它会把 JSP 的编码方式看成是 xx;否则,它会检查 JSP 中 是 否 有 <% @ page contentType=”text/html; charset=yy”%> 这行语句,如果有,它会把 JSP 的编 码方式看成是 yy;如果两者都无,它会把 JSP 的编 码方式默认看成 ISO- 8859- 1。确定了 JSP 的编码 方式后(尽管不一定与实际相符),Tomcat 会将 JSP 从该编码方式转换为 UNICODE 编码[2],并将 U- NICODE 编码的 JSP 编译为 Servlet 类文件,然后将 Servlet 类文件从 UNICODE 编码转换为 UFT- 8 编 码,并保存在磁盘上。 2.载入运行 JSP 编译成的 Servlet 类文件被载入内存运行 时,Tomcat 会将 Servlet 类文件由 UFT- 8 编码转换 回 UNICODE 编码。因为 UFT- 8 编码和 UNICODE 编码是一一对应的,UFT- 8 和 UNICODE 间的相互 转换不会导致乱码问题。 3.输出到 IE Servlet 将信息输出到 IE 之前,Tomcat 会检查 其 对 应 的 JSP 中 是 否 有 <%@ page contentType=” text/html;charset=xx”%> 这行语句。如果有,Tomcat 会将输出信息由 UNICODE 编码转换为 xx 编码, 然后输出到 IE,IE 的编码方式也会自动被设置为 xx;如 果 JSP 中没有以上语句,但有 <% @page pageEncoding=”yy”%> 这行语句,Tomcat 会将输出 信息由 UNICODE 编码转换为 yy 编码,然后输出 到 IE,IE 的编码方式也会自动被设置为 yy;如果 JSP 中以上两种语句都没有,Tomcat 会将输出信息 由 UNICODE 编码默认转换为 ISO- 8859- 1 编码,然 后 输 出 到 IE,IE 的编码方式会被自动设置为 ISO- 8859- 1。 通过以上分析可以看出,Tomcat 环境下的 JSP 被 IE 访问时要经过“编码方式 A→UNICODE→编 码方式 B”这样一个过程,这一过程中的错误编码 转换会导致问题一的出现。问题一通常由以下两 种情况造成: 情 况 一 :JSP 中 没 有 包 含 语 句 <% @page pageEncoding=”xx”% > 和 <% @ page contentType=” text/html;charset=yy”%>。假设 JSP 中有一汉字“的” (以下都以“的”字为例),现分析为什么“的”字在 IE 中显示时会变成乱码。在中文操作系统中,JSP 以 GB2312- 80 编码保存,因此,JSP 文件中“的”字 的编码为 0XB5C4。因为 JSP 中没有 以上两种语 句,在对 JSP 进行编译时,Tomcat 会把 JSP 的编码 方式默认当作 ISO- 8859- 1,从而将 0XB5C4 转换为 UNICODE 编码 U00B5U00C4。Servlet 输出信息到 IE 时,因 JSP 源文件中没有以上两种语句,Tomcat 会 将 UNICODE 编码 U00B5U00C4 转换为 ISO- 8859- 1 编码 0XB5C4,然后输出到 IE。因为 IE 的编码方式 会被自动设置为 ISO- 8859- 1,它将编码 0XB5C4 显 示为乱码“μ?”。 情 况 二 :JSP 中同时包含有语句 <% @page pageEncoding=”xx”% > 和 <% @page contentType=” text/html;charset=yy”%>,但 xx 和 yy 之中只有一个 为 GB2312- 80,另一个为 ISO- 8859- 1。如果 xx 为 GB2312- 80,yy 为 ISO- 8859- 1,“的”字在输出时, 它的 编码会经历 0XB5C4→U7684→0X3F 这 样 一 个转换过程,最终在 IE 中显示为一个“?”号。如果 xx 为 ISO- 8859- 1,yy 为 GB2312- 80,“的”字在输出 时,它的编码会经历 0X B5C4→U00b5U00c4→ 0XA6CC0X3F 这样一个转换过程,最终在 IE 中显 示为“μ?”这样两个乱码字符。 解决问题一的方法很简单,只要在 JSP 中包含 语 句 <% @page pageEncoding=”GB2312- 80”% > 或 <%@ page contentType=”text/html;charset=GB2312- 80”%> 即可,这样就可以保证 JSP 中的中文内容在 编译时由 GB2312- 80 编码转换为 UNICODE 编码, 在输出时由 UNICODE 编码 转 换 回 GB2312- 80 编 码。如果要在 JSP 中同时使用这两种语句,要确保 130 第 4 期 2011 年 两种语句中的编码方式都为 GB2312- 80。 (二)问题二、问题三的分析和解决 除了被 IE 直接访问,JSP 还可以被表单调用, 从而实现表单输入信息由 JSP 接收后再输出到 IE 显示。表单调用 JSP 时,实质上是调用其编译而成 的 Servlet。表单输入信息由 IE 传给 Tomcat,再由 Tomcat 传给运行中的 Servlet,最后由 Servlet 输出到 IE 进行显示。之前已对 Servlet 输出信息到 IE 时出 现的编码转换进行过分析,这里不再赘述,接下来 只对表单输入信息经 Tomcat 传递给 Servlet 时出现 的编码转换进行分析。表单调用 JSP 时,通常采取 两种方式:POST 方式和 GET 方式。 1.POST 方式 在 POST 方式下,表单输入数据放在 IE 请求 消息的实体部分传给 Tomcat。Servlet 中的 Request 对象通过 getParameter 方法向 Tomcat 请求表单输 入数据时,Tomcat 会检查 Request 对象的编码方式 属性。如果在 Request 对象调用 getParameter 方法 之前,其编码方式属性已通过 request.setCharac- terEncoding(“xx”)语句被设置成 xx,Tomcat 会把输 入数据的编码方式看成是 xx。如果 Servlet 中没有 这行语句,Tomcat 会将输入数据的编码方式默认 看成是 ISO- 8859- 1。确定了表单输入数据的编码 方式后(尽管不一定与实际相符),Tomcat 会将输 入数据从该编码方式转换为 UNICODE 编码,然后 传递给 Servlet[3]。 可以发现在 POST 方式下,表单输入数据通过 JSP 输出到 IE 时,同样要经历“编码方式 A→UNI- CODE→编码方式 B”这样一个过程,这一过程中 的错误编码转换会导致问题二的出现。问题二通 常由以下两种情况造成(假定在这两种情况中,表 单所在的 HTML 页面的编码方式都为 GB2312- 80, 那么表单中的汉字信息在传给 Tomcat 时,编码方 式都为 GB2312- 80): 情况一:JSP 中既没有语句 <%@page pageEn- coding=”xx”% > 和 <% @ page contentType=”text ml; charset=yy”%>,也没有语句 request.setCharacterEn- coding (“zz”)。因为 JSP 中没有语句 request.setChar- acterEncoding (“zz”),Tomcat 会将表单输入数据的编 码方式看成是 ISO- 8859- 1,并转换成 UNICODE 编 码 , 因 此“的 ”字 的 编 码 会 从 0XB5C4 转 换 为 U00B5U00C4。Servlet 输出信息到 IE 时,因为 JSP 中 没 有 语 句 <% @page pageEncoding=”xx”% > 和 <%@ page contentType=”text ml;charset=yy”%>,Tom- cat 会将编码 U00B5U00C4 转换为 ISO- 8859- 1 编码 0XB5C4,并输出到 IE。因为 IE 的编码方式会被自 动设置为 ISO- 8859- 1,编码 0XB5C4 显示为乱码 “μ?”。 情况二:JSP 中包含有语句 <%@page pageEn- coding=”GB2312- 80”%> 或 <%@page contentType=” text ml;charset=GB2312- 80”%>,但没有语句 request. setCharacterEncoding(“zz”)。情况二和情况一的不同之 处 在 于 :情 况 二 的 JSP 中 包 含 了 语 句 <% @page pageEncoding=”GB2312- 80”%> 或 <%@page content- Type=”text ml;charset= GB2312- 80”%>,因此”的“字 被 Servlet 输出到 IE 时,它的编码会从 U00B5U00B4 转换为 GB2312- 80 编码 0XA6CC0X3F,输出到 IE 显示为“μ?”这样两个乱码字符。 解决问题二有两种方法。 方 法 一 : 确 保 JSP 中 包 含 有 语 句 <% @page pageEncoding=”GB2312- 80”%> 或 <%@page content- Type=”text ml;charset=GB2312- 80”%>,此外,在 Re- quest 对象调用 getParameter 方法之前加上语句 re- quest.setCharacterEncoding(“GB2312- 80”)。这种方法 可确保表单中输入的中文信息通过 JSP 输出到 IE 时 会经过 GB2312- 80→UNICODE→GB2312- 80 这样一 个正确的编码转换过程。 方 法 二 : 确 保 JSP 中 包 含 有 语 句 <% @page pageEncoding=”GB2312- 80”%> 和 <%@page content- Type=”text ml;charset=GB2312- 80”%>,此外,将 Re- quest 对象调用 getParameter 方法的语句改为 String Output=new (request.getParameter (“Input”).getBytes (“ISO8859_1”)),然后输出字符串 Output 即可。现说 明一下这种方法为什么可行。在 request.getParameter (“Input”)执行之前,并没有设置 Request 对象的编码 方式,因此表单中汉字的编码方式被当成是 ISO- 8859- 1,然后转换成 UNICODE 传给 Servlet,因 而,“的”字的编码从 0XB5C4 转换为 U00B5U00C4。 调用了 getBytes(“ISO8859_1”)方法后,“的”字的编码 又变回了 0XB5C4,相当于又变成了 GB2312- 80 编 码 。 通 过 new 方 法 生 成 字 符 串 Output 时 ,该 GB2312- 80 编码会转换成对应的 UNICODE 编码。 在字符串 Output 被输出时,字符串的内容从 UNI- CODE 编码转换成 GB2312- 80 编码输出。通过以上 分析发现,该方法可确保表单中输入的中文信息 通过 JSP 输出时会经过 ISO- 8859- 1→UNICODE→ ISO- 8859- 1 (GB2312- 80)→UNICODE→GB2312- 80 这样一个正确的编码转换过程。 彭 立:Tomcat 环境下 JSP 中文乱码问题的解决 131 第 4 期 2011 年湖南 学院学报 Abstract:Chinese lousy code problems on Web server Tomcat have been puzzling software developers. To solve this problem, one should analyze the conversion between every encoding and find the reason that Chinese lousy code problems are caused by false encoding- conversion processes. Then a solution to the problem may be found after a further analysis of each wrong case. Key words:Tomcat; JSP; Chinese lousy code; encoding; conversion [责任编辑:胡 伟] The Solution to Chinese Lousy Code Problems of JSP on Tomcat PENG Li (Department of Information Science and Engineering, Hunan First Normal University, Changsha, Hunan 410205) 2.GET 方式 在 GET 方式下,表单输入数据放在 IE 请求消 息的请求行之中传给 Tomcat。通过查看 Tomcat 的 源代码可以发现,Tomcat 对 GET 方式下表单输入 数据的处理采用了和 POST 方式不同的方法。当 Request 对象通过 getParameter 方法向 Tomcat 请求 表单输入数据时,Tomcat 不会检查 Request 对象的 编码方式属性,而是检查配置文件 server.xml 中 port 值为 8080 的 connector 元素的 URIEncoding 属 性,并将表单输入数据的编码方式看成 URIEncod- ing 属性所设置的编码方式。如果 server.xml 中 port 值为 8080 的 connector 元素没有对 URIEncoding 属 性进行设置,Tomcat 会将输入数据的编码方式默 认当作 ISO- 8859- 1[4]。 知道了 Tomcat 在 GET 方式下对表单输入数 据所采用的处理方法,不难为问题三找到解决办 法,主要有两种: 方 法 一 : 确 保 JSP 中 包 含 有 语 句 <% @page pageEncoding=”GB2312- 80”%> 或 <%@page content- Type=”text ml;charset=GB2312- 80”%>,此外,将配置 文件 server.xml 中 port 值为 8080 的 connector 元素的 URIEncoding 属性设置为 GB2312- 80。这种方法可确 保表单中输入的中文信息通过 JSP 输出到 IE 时会经 过 GB2312- 80→UNICODE→GB2312- 80 这样一个正 确的编码转换过程。 方 法 二 : 确 保 JSP 中 包 含 有 语 句 <% @page pageEncoding=”GB2312- 80”%> 和 <%@page content- Type=”text ml;charset=GB2312- 80”%>,此外 ,将 JSP 中 Request 对象调用 getParameter 方法的语句改为 String Output=new (request.getParameter (“Input”).get- Bytes(“ISO8859_1”)),然后输出字符串 Output 即可。 此方法可行的原因和问题二的方法二相同,此处不 再累述。这种方法可确保表单中输入的中文信息通 过 JSP 输 出 到 IE 时 会 经 过 ISO- 8859- 1 →UNI- CODE →ISO- 8859- 1 (GB2312- 80) →UNICODE → GB2312- 80 这样一个正确的编码转换过程。 六、结语 Tomcat 环境下 JSP 中文乱码问题的根源是错误 的编码转换过程,对各种出错情况进行分析后,不难 找出这些问题的解决办法。以上分析对解决 Tomcat 环境下其他类型的中文乱码问题也具有指导作用。 文中的测试都是在 Tomcat5.0.28 下进行的,所有的解 决方法都在该版本下验证通过。 参考文献: [1]Jrnefors O.A short overview of ISO/ IEC 10646 and Uni code[DB/ OL].http:/ / www.nada.kth.se/ i18n/ ucs/ unicode- iso10646- oview.html [2]Lindenberg N.Developing Multilingual Web Applications Using JavaServer Pages Technology[DB/ OL].http:/ / java. sun.com/ developer/ technicalArticles/ Intl/ MultilingualJSP/ index.html [3]孙卫琴,李洪成.Tomcat 与 Java Web 开发技术详解[M].北 京:电子工业出版社,2004. [4]Apache Software Foundation.Apache Tomcat Configuration Reference The HTTP Connector[DB/ OL].http:/ / tomcat. apache.org/ tomcat- 5.5- doc/ config/ http.html 132
还剩4页未读

继续阅读

下载pdf到电脑,查找使用更方便

pdf的实际排版效果,会与网站的显示效果略有不同!!

需要 3 金币 [ 分享pdf获得金币 ] 0 人已下载

下载pdf

pdf贡献者

姚栋杰

贡献于2013-09-12

下载需要 3 金币 [金币充值 ]
亲,您也可以通过 分享原创pdf 来获得金币奖励!
下载pdf