JSP/Servlet 中的汉字编码问题

2019-05-27 09:20:15王振洲


Byte-->Unicode, 如果Byte标识的字符在源代码集不存在,则得到的结果是0xfffd.
如:
Byte ba[] = {(byte)0x81,(byte)0x40,(byte)0xb0,(byte)0xa1}; new String(ba,"??????");
结果是"?啊", hex 值是"ufffdu554a". 0x8140 是GBK字符,按??????转换表没有对应的值,取ufffd. (请注意:在显示该uniCode时,因为没有对应的本地字符,所以也适用上一种情况,显示为一个"?".)

实际编程中,JSP/Servlet 程序得到错误的汉字信息,往往是这两个过程的叠加,有时甚至是两个过程叠加后反复作用的结果.

4. JSP/Servlet 汉字编码问题及在 WAS 中的解决办法

4.1 常见的 encoding 问题的现象
网上常出现的 JSP/Servlet encoding 问题一般都表现在 browser 或应用程序端,如:
浏览器中看到的 Jsp/Servlet 页面中的汉字怎么都成了 '?' ?
浏览器中看到的 Servlet 页面中的汉字怎么都成了乱码?
JAVA 应用程序界面中的汉字怎么都成了方块?
Jsp/Servlet 页面无法显示 GBK 汉字。
JSP 页面中内嵌在<%...%>,<%=...%>等Tag包含的 JAVA code 中的中文成了乱码,但页面的其它汉字是对的。
Jsp/Servlet 不能接收 form 提交的汉字。
JSP/Servlet 数据库读写无法获得正确的内容。
隐藏在这些问题后面的是各种错误的字符转换和处理(除第3个外,是因为 Java font 设置错误引起的)。解决类似的字符 encoding 问题,需要了解 Jsp/Servlet 的运行过程,检查可能出现问题的各个点。

4.2 JSP/Servlet web 编程时的 encoding 问题
运行于Java 应用服务器的 JSP/Servlet 为 Browser 提供 HTML 内容,其过程如下图所示:



其中有字符编码转换的地方有:

JSP 编译。Java 应用服务器将根据 JVM 的 file.encoding 值读取 JSP 源文件,编译生成 JAVA 源文件,再根据 file.encoding 值写回文件系统。如果当前系统语言支持 GBK,那么这时候不会出现 encoding 问题。如果是英文的系统,如 LANG 是 en_US 的 Linux, AIX 或 Solaris,则要将 JVM 的 file.encoding 值置成 GBK 。系统语言如果是 ??????,则根据需要,确定要不要设置 file.encoding,将 file.encoding 设为 GBK 可以解决潜在的 GBK 字符乱码问题


Java 需要被编译为 .class 才能在 JVM 中执行,这个过程存在与a.同样的 file.encoding 问题。从这里开始 servlet 和 jsp 的运行就类似了,只不过 Servlet 的编译不是自动进行的。对于JSP程序, 对产生的JAVA 中间文件的编译是自动进行的(在程序中直接调用sun.tools.javac.Main类). 因此如果在这一步出现问题的话, 也要检查encoding和OS的语言环境,或者将内嵌在JSP JAVA Code 中的静态汉字转为 Unicode, 要么静态文本输出不要放在 JAVA code 中。对于Servlet, javac 编译时手工指定-encoding 参数就可以了。


Servlet 需要将 HTML 页面内容转换为 browser 可接受的 encoding 内容发送出去。依赖于各 JAVA App Server 的实现方式,有的将查询 Browser 的 accept-charset 和 accept-language 参数或以其它猜的方式确定 encoding 值,有的则不管。因此采用固定encoding 也许是最好的解决方法。对于中文网页,可在 JSP 或 Servlet 中设置 contentType="text/html; charset=??????";如果页面中有GBK字符,则设置为contentType="text/html; charset=GBK",由于IE 和 Netscape对GBK的支持程度不一样,作这种设置时需要测试一下。