问题
想在数据库而不是属性文件中存储所有标签、信息和其他静态文本,同时还要使用bean:message标签来访问值。
解决方案
(1) 下载OJBMessageResources 的发布包,网址为http://urceforge. net/struts/ojb-message-resources.zip?download。
(2) 将ZIP 文件解压缩到计算机目录中。
(3) 从ojb-message-resources/dist 文件夹中复制ojb-msg-res.jar 文件到您的应用的WEB-INF/lib 文件夹下。
(4) 从ojb-message-resources/config 文件夹中复制属性、XML 和DTD 文件到您的应用程序的src 文件夹下。在构建应用程序时,这些文件必须复制到WEB-INF/classes 文件夹中。
(5) 建立表用于存储Objec Relational Bridge (OJB)元数据表。OJB 使用这些表来存储内部映射信息。例2.12显示了为MySQL 数据库创建的这些表(即数据定义的SQL)。其他数据库的有关语句包含在OJB中。
例2.12:OJB 元数据 DDL (MySQL)
CREATE TABLE ojb_dlist (
ID int NOT NULL default '0',
SIZE_ int default NULL,
PRIMARY KEY (ID)
) TYPE=MyISAM;
CREATE TABLE ojb_dlist_entries (
ID int NOT NULL default '0',
DLIST_ID int NOT NULL default '0',
POSITION_ int default NULL,
OID_ longblob,
PRIMARY KEY (ID)
) TYPE=MyISAM;
CREATE TABLE ojb_dmap (
ID int NOT NULL default '0',
SIZE_ int default NULL,
PRIMARY KEY (ID)
) TYPE=MyISAM;
CREATE TABLE ojb_dmap_entries (
ID int NOT NULL default '0',
DMAP_ID int NOT NULL default '0',
KEY_OID longblob,
VALUE_OID longblob,
PRIMARY KEY (ID)
) TYPE=MyISAM;
CREATE TABLE ojb_dset (
ID int NOT NULL default '0',
SIZE_ int default NULL,
PRIMARY KEY (ID)
) TYPE=MyISAM;
CREATE TABLE ojb_dset_entries (
ID int NOT NULL default '0',
DLIST_ID int NOT NULL default '0',
POSITION_ int default NULL,
OID_ longblob,
PRIMARY KEY (ID)
) TYPE=MyISAM;
CREATE TABLE ojb_hl_seq (
TABLENAME varchar(175) NOT NULL default '',
FIELDNAME varchar(70) NOT NULL default '',
MAX_KEY int default NULL,
GRAB_SIZE int default NULL,
PRIMARY KEY (TABLENAME,FIELDNAME)
) TYPE=MyISAM;
CREATE TABLE ojb_lockentry (
OID_ varchar(250) NOT NULL default '',
TX_ID varchar(50) NOT NULL default '',
TIMESTAMP_ decimal(10,0) default NULL,
ISOLATIONLEVEL int default NULL,
LOCKTYPE int default NULL,
PRIMARY KEY (OID_,TX_ID)
) TYPE=MyISAM;
CREATE TABLE ojb_nrm (
NAME varchar(250) NOT NULL default '',
OID_ longblob,
PRIMARY KEY (NAME)
) TYPE=MyISAM;
CREATE TABLE ojb_seq (
TABLENAME varchar(175) NOT NULL default '',
FIELDNAME varchar(70) NOT NULL default '',
LAST_NUM int default NULL,
PRIMARY KEY (TABLENAME,FIELDNAME)
) TYPE=MyISAM;
(6) 创建表,使用例2.13显示的SQL DDL存储信息资源数据。
例2.13:MessageResources DDL
create table application_resources (
subApp varchar(100) not null,
bundleKey varchar(100) not null,
locale varchar(10) not null,
msgKey varchar(255) not null,
val varchar(255),
Primary Key(
subApp,
bundleKey,
locale,
msgKey
)
);
(7) 根据信息资源构建表。例2.14显示了一个简单的用SQL加载表的方法。
例2.14:使用SQL 加载消息资源表
insert into application_resources (
subApp, bundleKey, locale, msgKey, val )
values ('', '', '', 'label.index.title',
'Struts Cookbook');
insert into application_resources (
subApp, bundleKey, locale, msgKey, val )
values ('', '', 'fr', 'label.index.title',
'Struts Livre de Cuisine');
(8) 修改Struts 配置文件,以便使用OJBMessageResources Factory。
<message-resources
factory="org.apache.struts.util.OJBMessageResourcesFactory"
parameter="."
/>
(9) 修改WEB-INF/classes 文件夹中的repository.xml(前三步相同),并对数据库使用数据库链接属性。例2.15 显示了MySQL 数据库的配置文件。
例2.15:MySQL的OJB连接描述符
<jdbc-connection-descriptor
platform="MySQL"
jdbc-level="2.0"
driver="com.mysql.jdbc.Driver"
protocol="jdbc"
subprotocol="mysql"
dbalias="//localhost:3306/test"
username="user"
password="pass"
/>
讨论
Struts MessageResources 的职能是管理静态文本,如错误信息、字段标签、表题以及窗口标题。利用这种功能,文本以name/value 对的形式存储在一个或多个.properities文件中。这个文件就是信息资源,名称是逻辑键,值则是要显示的文本。如果应用程序需要针对某种语言和国家,可以创建新的属性文件。增加语言和国家编码所组成的前缀将文件与其特定范围(语言和国家)联系起来。例如,法裔加拿大用户的 MessageResources.properties 文件为MessageResources_fr_CA.properties。在本地文件中,属性具体包含到某个地区的值。这种本地化资源的方法由 Java本身定义。
这样的职能适用于大多数中小型应用程序。您或许想用更便于管理的、持久的方式来存储文本,例如数据库。但Struts 不支持这种直接操作,而是通过扩展来支持。实际上,Struts 运用MessageResourcesFactory来创建MessageResources 对象,并在运行时存储在servlet 上下文中。可以提供一个MessageResourcesFactory 的自定义实现,然后在配置文件中声明这个实现:
<message-resources
factory="com.foo.CustomMessageResourcesFactory"
parameter="moduleName.bundleKey"
/>
参数属性定义了Struts 的模块名称以及bundle键(bundle名),信息资源库为它创建了信息。由此,可以创建自己的信息资源库,从数据库中读取消息。谢天谢地,这种想法已经得以实现!James Mitchell,一个长期设计Struts的人,已经实现了OJBMessageResources,这个类集合调整了对象相关型映射框架OBJ,提供了一个使用简便的数据库驱动MessageResource的实现方法。
如果对OJB不熟悉,不要因此而放弃使用这种方法。不需要了解OJB 就能使用OJBMessageResources。使用OJB将关系数据映射到对象数据非常简单。如果使用解决方案中的表架构,不需要做任何修改就可以映射数据。但如果想使用不同的架构,可以修改OJB基于XML中配置文件的映射来满足需要。不需要修改Java编码就能实现MessageResourcesFactory。OJBMessageResources文档健全并且配有安装向导和README文件。上述解决方案来自于这些说明。
为了更有效地使用OJBMessageResources,了解数据库架构如何映射到目标数据是很有帮助的。首先,架构仅需要创建一个表来存储信息资源,使用单独的表就简化了数据映射。表2.2描述了表的组成及其在struts中的用法。
表2.2:OJBMessageResources架构
列名称
|
相关的Struts概念
|
说明
|
subApp
|
模块前缀
|
非空。用空字符串 ("") 来代表默认模块
|
bundleKey
|
使用多个集合时定位信息资源集合的键。它的值必须与Struts配置文件中message-resource元素key属性的值匹配。该值与Struts标签bundle属性的值相关(例如,bean:message bundle="labels")
|
非空。用空字符串 ("") 来代表默认键。其他的名称分别为逻辑名"labels","headers"和"errors"
|
Locale
|
本地编码代表本地信息。它的值是双字母语言编码和双字母国家编码的结合
|
非空。U用空字符串("")来代表默认区域。例如,"en_US" 表示English/United States,"fr" 表示 French
|
msgKey
|
用于查找信息的信息名称。对于所有的区域均相同. 它等于属性文件中属性左边的值。该值与Struts 标签中从MessageResources获得的值的key属性值相关
|
非空,任何时候都不为空。例如"title.hello.world"
|
val
|
与msgKey相关的值。它是本地文本,与属性的右边值相关,由Struts标签获取和显示
|
可为空。这是页面上显示的文本。例如, "Hello, World!"
|
注意,当OJBMessageResources使用单独的数据库表来存储所有的信息资源时,每个信息资源必须在struts-config.xml文件中使用message-resources元素进行配置。换句话说,就是需要用bundleKey和 subApp为每一个信息资源配置一个message-resource加以标识。2.6节叙述了更多细节。
相关链接
2.6节叙述了如何使用多个信息资源配置Struts。第14章介绍了Struts应用程序国 际化。
OJB 是Apache下的项目。关于OJB的完整信息可参见http://db./ojb。
人们正在努力将Struts 信息资源分解为可重新利用的通用类。关于Commons Resources 项目,http://jakarta./commons/sandbox/resources/提供一个由属性文件和其他持久化机制组成的信息资源的实现,这些机制包括OBJ、Hibernate、Torque和直接使用JDBC。希望在Struts的下一个版本能够实现封装Commons Resources的内部信息资源