级别: 初级 Peng De Hua (pengdh@cn.ibm.com), 软件工程师,上海全球实验室, IBM 中国
2004 年 12 月 01 日 许多应用程序框架在按需(On Demand)业务环境下具备全球化特征。JavaServer Faces(JSF)是基于模型—视图—控制(Model-View-Controller,MVC)结构的 J2EE 应用程序的用户接口框架。它也具备全球化的特征。本文向您展示了如何使用 JSF 和 WebSphere Studio Application Developer V5.1.2 来开发全球化 Web 应用程序。
引言
全球化发生在 JSF 请求流程生命周期中的某些时刻,然而可以很容易地说明用函数来中止任务后将要发生什么。本文通过逐步使用 IBM© WebSphere© Studio Application Developer V5.1.2 的例子来说明 JSF 的全球化特征。主题包括确定活动位置、创建并纪录指定位置的数据、检索指定位置的数据,以及定位应用程序的信息。
假设
假设我们有一个称为 LoginSample 的非全球化的动态 Web 应用程序。它包括两个 JSP 文件——
login.jsp 和
success.jsp。
login.jsp 具备标识符为
username 的 Input 组件用于输入用户名,标识符为
password 的 Input-Password 组件用于输入口令,两个 Output 组件用于显示
username 和
password,以及标识符为
button1 的 Command-Button 组件用于提交请求。注册后,用户的信息将被发送到显示成功信息的
success.jsp 页面,或者返回到
login.jsp 页面。
login 方法是在
Login.java 中,它在页面代码包中被自动地生成。我们假定您已经在
doButton1Action() 方法中编写了 Faces 命令事件来处理
login。
1. 确定活动位置
目前全球化通常是以位置为基础的,它把数据集和特定的规则分成了语言区域和地理区域两类。
JSF 也是以它为基础并且使用活动的位置来查找所有的地方化资源。活动位置作为当前
FacesContext 的
UIViewRoot 中的位置 JavaBean 属性值来存储。您可以在应用程序的
WEB-INF/facesconfig.xml file 中告知 JSF 应用程序支持哪些位置。在应用程序
LoginSample 的
WEB-INF 目录下,您可以看到
faces-config.xml 文件夹,它不仅用来定义您所管理的 bean、
validator、converter,以及向导规则,而且也定义一些全球化的规则。
将下面的代码添加到
faces-config.xml 文件的
<faces-config> 元素中。
<application>
<locale-config>
<default-locale>en_US</default-locale>
<supported-locale>zh_CN</supported-locale>
</locale-config>
</application>
|
locale-config 元素使得系统能够依据浏览器的语言设定来找出正确的位置。Web 应用程序默认的位置是
en_US,并且它也支持
zh_CN。
2. 创建并纪录指定位置的数据
在全球化的 Web 应用程序中,指定位置的数据必须根据终端用户的语言和区域的习惯来剪裁。在用户界面显示的文本是最明显的指定位置的数据的例子。例如由
login.jsp 说明的两个输出组件的文本以及提交按钮。通常,您可以在 ResourceBundle 中隔离指定位置的对象。
JSF 也使用 ResourceBundle 作为地方化的 Pack,它由一系列属性文件来支持。
建立三个名为
ApplicationMessages.properties 的属性文件。选取
Java™ Resources => New => Other => Simple => File。输入
ApplicationMessages_en_US.properties 作为文件名后单击
Finish。在编辑过程中,输入下面几行,然后保存并关闭文件:
USER_NAME=User Name
PASSWORD=Password
SUBMIT=Login
|
新建文件
ApplicationMessages_zh_CN.properties,并添加内容相应的中文字符。为了实现全球化的目的,使用 JDK 中的
native2ascii.exe 将它们转换成 Unicode 转换码:
USER_NAME=\u7528\u6237\u540d
PASSWORD=\u5bc6\u7801
SUBMIT=\u63d0\u4ea4
|
Java Resource 目录下的文件
ApplicationMessages_en_US.properties 和
ApplicationMessages_zh_CN.properties 分别作为
en_US 和
zh_CN。这些文件编译后将被复制到您的
classes 目录下。项目层次如图 1 所示:
图 1.项目层次
在应用程序启动时如何使得 ResourceBundle 有效?您有两种选择:用编程的方法将
FacesContext 实例中的信息排队(如下面第 4 步中所述),或者通过使用
WEB-INF 目录下的应用程序配置资源文件
faces-config.xml 来注册您应用程序的信息。
将下面的内容
faces-confi.xml 添加到应用程序元素中
<message-bundle>
ApplicationMessages
</message-bundle>
|
faces-confi.xml 目前看起来是这样的:
图 2. Faces-confi.xml
消息捆绑元素代表了一套地方化的信息,并且将使您的应用程序实例同指定的 ResourceBundle 中包含的信息组装起来。它必须包括到含有地方化信息(本例中是 ApplicationMessages)的 ResourceBundle 的完整的路径。
3.检索指定位置的数据
为了便利,JSF 提供了
<f:loadBundle> 标签,它获取 ResourceBundle 并将其装载到 Map 中,然后将其存储到请求领域的命名空间中,这样使得用同一机制在模型层中访问数据所得到的信息是有效的。例如:
<f:loadBundle basename="ApplicationMessages" var="messages" />
|
然后我们可以通过使用
#{messages.key} 从属性文件中检索键码的值。确保您的 ResourceBundle 包含您用这些标签指定位置的主键信息。
将代码添加到
login.jsp 使得两个标签上的文本以及 Submit 按钮的文字说明能够全球化。
login.jsp 目前看上去是这样的:
<%-- jsf:codeBehind language="java" location="/JavaSource/pagecode/Login.java" --%><%-- /jsf:codeBehind --%>
<HTML>
<HEAD>
<%@taglib uri="http://java.sun.com/jsf/html" prefix="h"%>
<%@taglib uri="http://www.ibm.com/jsf/html_extended" prefix="hx"%>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<f:loadBundle basename="ApplicationMessages" var="messages" />
<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
<META name="GENERATOR" content="IBM WebSphere Studio">
<META http-equiv="Content-Style-Type" content="text/css">
<LINK href="theme/Master.css" rel="stylesheet" type="text/css">
<TITLE>login.jsp</TITLE>
<LINK rel="stylesheet" type="text/css" href="theme/stylesheet.css" title="Style">
</HEAD>
<f:view>
<hx:scriptCollector id="scriptCollector1">
<h:form styleClass="form" id="form1">
<P align="center">
<h:outputLabel styleClass="outputLabel" id="label1"
value="#{message.USER_NAME}" for="username"></h:outputLabel>
<h:inputText styleClass="inputText" id="username"></h:inputText><BR>
<h:outputLabel styleClass="outputLabel" id="label2" for="password"
value="#{message.PASSWORD}"></h:outputLabel>
<h:inputText styleClass="inputSecret" id="password"></h:inputText><BR>
<hx:commandExButton type="submit"
value="#{message.SUBMIT}" styleClass="commandExButton" id="button1"></hx:commandExButton>
</P>
</h:form>
</hx:scriptCollector>
</f:view>
</HTML>
|

 |

|
4.使应用程序的信息停留在某一位置
除了用于标签,按钮上的文本,工具的提示等地方化的数据以外,由于转化、确认或者其他的在请求流程生命周期中的应用程序行为而产生的错误以及提示信息也应被地方化。JSF 类
javax.faces.application.FacesMessage 封装了消息的概要、详细以及严密的信息。JSF 提供一些标准的信息——更多的信息,详见
JavaServer Faces 1.0 规范。
JSF 应用程序能通过使用应用程序配置资源中提供的
<message-bundle> 元素来包含标准信息。这些 ResourceBundle 主键用于查找必要的值来创建位置固定的 FacesMessage 实例。例如,LoginSample 应用程序用一些自定义的错误信息来取代标准消息。
将下面的内容添加到文件
ApplicationMessages_en_US.properties 中,主键为
javax.faces.component.UIInput.REQUIRED 的消息取代了标准消息,主键为
INVALID_USER_PASSWORD 和 DATABASE_ERROR 的消息是自定义的错误信息:
javax.faces.component.UIInput.REQUIRED=User name can not be empty.
INVALID_USER_PASSWORD=Your user name or password is wrong, please try again.
DATABASE_ERROR =There is some error about database, please contact administrator.
|
这里是
ApplicationMessages_zh_CN.properties 响应的中文 Unicode 转换码:
javax.faces.component.UIInput.REQUIRED=\u7528\u6237\u540d\u4e0d\u80fd\u4e3a\u7a7a\u3002
INVALID_USER_PASSWORD=\u7528\u6237\u540d\u6216\u5bc6\u7801\u9519\u8bef\uff0c\u8bf7\u91cd\u8bd5\u3002
DATABASE_ERROR=\u6570\u636e\u5e93\u4e0d\u80fd\u7528\uff0c\u8bf7\u8054\u7cfb\u7ba1\u7406\u5458\u3002
|
页面可以通过使用
UIMessage 和
UIMessages 组件来显示这些消息,它们相应的标签是:
<h:message> 和
<h:messages>。
向 Web 应用程序中添加一些控制来显示地方化的消息。首先,添加字符串变量来记录
Login.java 中发生的错误种类:
在 Design 视图下,右键单击
login.jsp 中的
login 按钮,并选取
Edit Faces event 以打开
Login.java。定位到
doButton1Action() 方法并且用下面的代码取代原有的内容:
public String doButton1Action() {
//get user name and password from the login.jsp
String username = (String) requestScope.get("username");
String password = (String) requestScope.get("password");
//access database for login
Connection connection = null;
Statement stmt = null;
ResultSet rs = null;
String key = ""; // type of error
try {
Class.forName("COM.ibm.db2.jdbc.app.DB2Driver");
connection = DriverManager.getConnection("jdbc:db2:user","db2admin","db2admin");
stmt = connection.createStatement();
String sql = "select * from user where username='" + username + "' and password='" + password + "'";
rs = stmt.executeQuery(sql);
if (rs.next())
return "success"; //for navigation
else
key = "INVALID_USER_PASSWORD";
} catch (ClassNotFoundException cnfex) {
System.out.println(cnfex.toString());
} catch (SQLException sqle) {
key = "DATABASE_ERROR";
}
return "false";
}
|
将
<h:messages> 添加到文件
login.jsp 中来显示错误信息。
在 Design 视图下选取
login.jsp 中的
username 的
inputText,将出现一个 Attribute 视图。选取Validation 选项卡中的
Vale is required 和
Add display error control 复选框,然后保存文件。这将在用户姓名输入框后添加
<h:message> 标签,当您提交了包含空的用户姓名
inputText 的表单后将通过主键
javax.faces.component.UIInput.REQUIRED 显示错误信息。对于简单的情况,我们使用
<h:messages> 标签来显示所有的错误,因此应删除
<h:message> 标签并向文件
login.jsp 中添加
<h:messages> 标签。
装载地方化的动态消息。
正如上面所讨论的,您可以通过编程的方式将消息在 FacesContext 中排队。从当前请求的
UIViewRoot 中获得当前的位置并且通过使用
getBundle 方法将地方化的数据装载到消息中,通过路径传到 ResourceBundle 以及当前的位置中。下面我们使用这种方法来装载错误消息并且使用
FacesContext.addMessage(String clientId, FacesMessage message) API 来将消息添加到
<h:messages> 标签中。将下面的代码添加到
Login.java 并且
在返回
false 之前添加一个
statement getmessage("",key) to doButton1Action() 方法:
protected void getmessage(String clientId, String key) {
// Look up the requested message text
String text = null;
try {
ResourceBundle bundle =
ResourceBundle.getBundle( "ApplicationMessages", getFacesContext().getViewRoot().getLocale());
text = bundle.getString(key);
} catch (Exception e) {
System.out.println(e.toString());
}
// Construct and add a FacesMessage containing it
getFacesContext().addMessage( clientId,
new FacesMessage(FacesMessage.SEVERITY_ERROR, text, text));
}
|
范例
作为 WebSphere Studio V5.1.2 的 WAR 文件来导出
LoginSample 项目并将它部署到 WebSphere Application Server V5.1。例如,将它部署到
localhost 的
/loginsample 中:
选取
English (United States) [en_US] 作为您浏览器的首选语言。在 IE 中选取
Tools => Internet Options => General => Languages。打开 Language Preference 对话框:
图 3.选择首选语言
将 Web 浏览器地址设为
http://localhost:9080/loginsample/faces/login.jsp,您就可以看到登录界面,如图 4 所示。User Name、Password 输出字段以及 Login 按钮上的文字说明都是英文的。
如果您在 User Name 空缺的情况下单击
Login,将得到
javax.faces.component.UIInput.REQUIRED 的错误信息,如图 5 所示。
如果您输入了有效的用户名或口令并单击
Login,将得到来自于 Resource bundle 的
INVALID_USER_PASSWORD 错误信息,如图 6 所示。
如果数据库出现了错误,您将得到
DATABASE_ERROR 的错误信息,如图 7 所示:
英文例子
图 4
图 5
图 6
图 7
如果您将浏览器的首选语言从
en-US 改为
zh-CN,然后进行上述流程,将会看到 Web 站点以简体中文的方式显示,如图 8—11 所示:
中文例子
图 8
图 9
图 10
图 11
结束语
本文描述了 JavaServer Faces 的全球化特征并且提供了范例,通过使用 WebSphere Studio Application Developer V5.1.2 来一步一步地创建全球化的 Web 应用程序。如果您要求语言的地方化,那么就需要设计资源包使其包含所有需要的语言。
参考资料
关于作者  | |  |
Peng De Hua 是 IBM 上海全球实验室中的软件工程师。他在技术开发组工作,检查 IBM 旗舰产品的全球互用性,并从全球化角度提出产品的改进意见。您可以通过
pengdh@cn.ibm.com 来联系他。
|
对本文的评价
|