JAVA编程/WAS对多语言(双字节)的支持

1. 双字节支持概述

在目前的计算机应用中,英文字符最常用的编码方法是 ASCII,一般以一个字节来表示。但一个字节最多只能区分256个字符。而其他的语言,以汉字为例,汉字成千上万,仅以一个字节无法表示。所以现在都以双字节表示汉字。我们在国内经常碰到的编码方式有 GB2312、GBK、UNICODE、以及国家质量技术监督局在2000年发布并作为一项国家标准正式强制执行的GB18030等。





回页首


2. 双字节支持前提和原理

虽然 Java 的基本类已考虑到对非英文的多语言支持(默认 UNICODE 编码),但是如果操作系统的默认编码不是 UNICODE ,要从 Java 源代码到得到正确的结果,就要经过一个较为复杂的过程。该过程为: "Java 源码 -> Java 字节码 -> Java虚拟机 -> 操作系统 -> 显示设备"。在该过程中,我们在每一步都必须正确地处理双字节/汉字的编码,才能够正确显示最终的双字节结果。

1) Java 源码 到 Java 字节码的双字处理

Javac(标准Java 编译器)使用的字符集为操作系统默认的字符集,比如在中文 Windows 操作系统上是 GBK/GB18030 ,而在英文UNIX 操作系统上就是ISO-8859-1。因此开发人员会发现在 英文UNIX 操作系统上编译的类,其中双字节(中文)字符都成了乱码或者问号。解决方案是在编译时添加 encoding 参数,就可以做到与平台无关。语法如下:



javac -encoding GBK

2) Java 字节码到Java虚拟机再到操作系统的双字处理

JRE (Java 运行环境) 分为国际版和英文版,其中只有国际版才支持非英文字符。JDK(Java 开发工具包) 都肯定支持非英文字符,但并非所有的服务器(或者开发平台)都会安装JDK 。很多操作系统及应用软件都会内嵌 JRE 的国际版本,例如WebSphere Application Server多语言版,为产品及其应用支持非英文字符提供了完全的支持。

3) 操作系统到显示设备的双字节处理

支持非英文字符的最基本条件是操作系统必须支持并能够显示它。如果是纯英文操作系统,如果不搭配特殊的应用软件,肯定不能够显示双字节字符(例如中文)。因此在实际环境中,特别是UNIX操作系统,要特别留意是否安装了多语言支持包。





回页首


3. J2EE编程对双字节的支持

我们接下来探讨在 Java 编程过程中,对非英文字符进行正确的编码转换。假设操作系统已经具备中文的字符集支持。下面以中文为例,示例如何正确处理和显示双字节字符。

1) JSP如何正确显示中文字符

注意下列代码中加重红字显示的部分:



<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<HTML>
<HEAD>
<%@ page language="java" contentType="text/html; charset=GB18030" pageEncoding="GB18030"%>
<TITLE>input.jsp</TITLE>
</HEAD>
<BODY>
<P>请输入您的姓名:</P>
<FORM action="/test/TestServlet" method="post">
<INPUT type="text" name="name" size="20"><INPUT type="submit"
	name="确定" value="确定"></FORM>
</BODY>
</HTML>

该页正确显示如下图:




如果去掉红色字体部分,JSP页面显示将会成乱码,如下图所示:




在这种情况下,如果点击浏览器菜单:查看 ' 编码,会发现页面目前的缺省编码为:"西欧(ISO)" 这时如果选择编码:"简体中文(GB18030)"(如下图所示),页面也能够正确显示汉字,但这种方式显然不能被最终客户端用户所接受,因此编成人员在开发时要尽力避免。




2) 与Servlet交互时如何正确显示中文字符

在页面与Servlet交互时是最容易产生中文字符问题的。因为在HTTP Request 和 HTTP Response在编码时缺省会基于ISO-8859-1,导致传入和传出Servlet的中文参数都编成了乱码或者问号。以上述的JSP作为客户端页面,我们来提交一个既有英文字符和中文字符的参数,提交方式采用HTTP POST方法。如下图所示:




下列代码为接收请求的Servlet的doPost方法:



protected void doPost(HttpServletRequest arg0, HttpServletResponse arg1)
		throws ServletException, IOException {
	
	String name = arg0.getParameter("name");
	String a = "您好:";
	System.out.println(a + name);
	PrintWriter out = arg1.getWriter();
	out.println(a + name);
	out.close();
}

由于代码中对于请求和响应的编码未做任何处理,因此返回给客户端的结果出现了"?",不能正确显示中文字符。如下图:




解决的方法有两种,一种是在WAS/RAD中设置参数进行自动编码,无需改动源码;另一种是通过改动源码编程实现。前者将在本文的第5节进行讨论。后者在J2EE 1.4中很方便实现,即对HttpServletRequest和HttpServletResponse都调用setCharacterEncoding方法。见下列代码中红色加重的字体。在J2EE 1.3中,还仅仅是HttpServletRequest有setCharacterEncoding方法,HttpServletResponse并未提供。



protected void doPost(HttpServletRequest arg0, HttpServletResponse arg1)
		throws ServletException, IOException {
	
	arg0.setCharacterEncoding("GB18030");
	String name = arg0.getParameter("name");
	String a = "您好:";
	System.out.println(a + name);
	
	arg1.setCharacterEncoding("GB18030");
	PrintWriter out = arg1.getWriter();
	out.println(a + name);
	out.close();
}

通过在Servlet中对HttpServletRequest和HttpServletResponse都进行了汉字编码,就可以保证传入和传出Servlet的汉字字符都能正确显示,如图:




4. 数据库读写时的双字节编码问题

JSP/Servlet 编程中经常出现编码问题,除了上述讨论的方面,另方面是读写数据库中的数据。

目前业界常用的关系数据库系统都支持数据库多语言编码,也就是说在创建数据库时可以指定它自己的字符集设置,数据库的数据就将以指定的编码形式存储。当应用程序访问数据时,在入口和出口处都会有 encoding 转换。对于中文数据,数据库字符编码的设置应当保证数据的完整性。GB2312、GBK、UTF-8、ISO-8859-1等都是可选的数据库编码。但是如果编码设置成了ISO-8859-1,则应用程序在写数据之前须将 16Bit 的一个汉字或 Unicode 拆分成两个 8-bit 的字符,读数据之后则需将两个字节合并起来,同时还要判别其中的 SBCS 字符。这种情况没有充分利用数据库编码的作用,反而增加了编程的复杂度。因此ISO-8859-1不是推荐的数据库编码。针对上述状况,下列代码示例了如果Java应用是基于GB18030编码,而数据库编码是ISO-8859-1的情况,如何通过Java代码转换字符而不会产生乱码:

1) 从数据库中读入含中文的字符串:



… …
PreparedStatement pst = … … ;
ResultSet rst = … … ;
… …
String result = rst.getString(1);	//从数据库得到某个字段的字符串结果
result = new String(result.getBytes("GB18030"));//对result的字符集重新进行编码,将其强制转为本地GB18030字符集
… … 

2) 将中文字符串写入数据库:



… …
PreparedStatement pst = … … ;
… … 
sql = new String(sql.getBytes(),"GB18030");	//对sql的本地编码按GB18030进行解码,还原为数据库能接受的代码
pst.execute(sql);
… …





回页首


5. WAS中的双字节支持

1) WAS提供对Web部署描述符的扩展功能:在ibm-web-ext.xmi文件中设置autoRequestEncoding和autoResponseEncoding 在 Web 模块上启用 autoRequestEncoding 设置会更改WAS的缺省行为:如果Http Request header上不存在字符集,则WAS检查Http Request的 Accept-Language 头,并使用头中找到的第一种语言进行编码。如果content type头上没有字符集,而且没有 Accept language 头,则WAS使用服务器上设置的字符编码,通过系统属性 default.client.encoding。当上述属性均未设置,则WAS使用 ISO-8859-1。

autoRequestEncoding和autoResponseEncoding参数可以在WSAD/RAD或者Application Server Toolkit (AST)中设置。开发人员可以打开WAR项目的部署描述符文件,如下图所示:




如果在该处进行了设置,就不需要在Servlet中采用编程处理Http Request和Http Response的中文编码问题。

2) 在管理控制台中启用多语言编码支持。

要在管理控制台中使用多语言编码支持,您必须配置应用程序服务器,例如启用 GB18030 编码。在"Java 虚拟机"页面上(应用程序服务器 > server1 > 进程定义 > Java 虚拟机),为通用 JVM 自变量指定 -Dclient.encoding.override=GB18030 (或者-Ddefault.client.encoding=GB18030) ,如下图所示:






关于作者

 

李珂嘉,IBM 软件部 WebSphere 专家。

 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值