导读:
级别: 高级
Brett D. McLaughlin, Sr.(
[email protected]), 作家兼编辑, O'Reilly Media, Inc.
2007 年 11 月 26 日
Castor 项目为开源领域提供了数据绑定功能。其原理跟 Sun 的 JAXB 很相似,并且向关系数据库表添加了增强的映射和绑定功能。在本文中,我们将讨论运行 Castor 所需的首要步骤,包括下载、安装、设置、配置、类路径问题等等。
数据绑定风靡一时
在 XML 新闻组、邮件列表和网站的讨论论坛中(在 参考资料中可以找到这些内容的链接),最常见的一个主题就是数据绑定。Java 和 XML 开发人员正在寻求一种在 Java 对象与 XML 文档之间来回转换的简单方法。
Sun 借助其 JAXB,即 Java Architecture for XML Binding(如果您在其他地方看到缩写词 JAXB,那也是正常的;Sun 似乎每年都会更改 JAXB 所代表的含义), 在数据绑定领域占据了主导地位。然而,JAXB API(如果您喜欢,也可以称为架构)存在着一些不足,并且更新速度较慢。它也不能处理到关系数据库的映射,而这种映射是一种很常见的请求。
Castor 的诞生
正是在这种情形下,Castor 出现了。Castor 是一种开源框架,它可用于无法使用 JAXB 的领域。Castor 一直在发展之中,并且早于 JAXB 代码库和 SUN 数据绑定规范。实际上,Castor 已经实现了更新,可结合 JAXB 方法实现数据绑定,因此使用 JAXB 的编程人员可以很容易地移动代码。
Castor 的优势
在讨论安装和使用 Castor 的细节之前,有必要指出尝试 Castor 以及从 JAXB 转变到 Castor 的理由。
首先,Castor 几乎是 JAXB 的替代品。换句话说,可以轻易地将所有 JAXB 代码转变为 Castor(并不是完全取代,但是足以使刚刚接触 Castor 的程序员轻松完成任务)。
其次,Castor 在数据绑定领域提供了许多的功能,无需使用模式便可在 Java 和 XML 之间进行转换,提供一种比 JAXB 更易于使用的绑定模式,以及能够对关系数据库和 XML 文档进行编组(marshal)和解组(unmarshal)。
Castor 还提供了 JDO 功能。JDO 也就是 Java Data Objects,是驱动 Java-to-RDBMS 编组和解组的底层技术。尽管不再像前几年那么流行,JDO 仍然是一个不错的功能。此外,由于 JDO 也是一种 Sun 规范,因此不用编写模糊的 API。
下载 Castor
Castor 的安装过程很简单。首先,访问 Castor Web 站点(参见 参考资料中的链接)并在左侧菜单中单击
Download。选择 latest milestone release,然后向下滚动到
Download sets。您可以下载 Castor JAR、DTD、doc、dependency 等所有内容,预打包的下载套件非常容易使用(参见图 1)。
图 1. Castor Web 站点的下载套件
在本文中,我们将使用版本 1.1.2.1。我选择 ZIP 格式的
The Castor JARs, docs, DTDs, command line tools, and examples下载套件。您将获得一个可以展开的归档文件,其中包含许多 JAR 文件、文档和示例程序(参见图 2)。
图 2. 展开的 Castor 归档文件
正确放置所有文件
接下来,需要将 Castor 的所有文件安放在系统中的正确位置,使您的 Java 环境能够访问它们。
将 Java 库放在同一个位置
我强烈建议将所有第三方 Java 库放在一个常见位置。您可以将它们随意散放在系统中,但是这样做会带来严重后果,因为如下原因:
在大多数情况下很难找到需要的东西。
您将会花大量时间来确定使用的库版本,因为您会经常将多个版本放在系统的不同位置。
类路径将会变得很长而且难于理解。
我将我的所有库放在 /usr/local/java/中,每个库放在自己的子目录中(各个目录通常带有一个版本号)。因此将 Castor 归档文件 —经过扩展 —移动到您常用的库位置。在本例中,Castor 的完整路径为:/usr/local/java/castor-1.1.2.1。
为 Castor JavaDoc 添加书签
在系统中设置 Java 库的另一个步骤是定位和链接到文档。您会经常这样做,而且大多数 Java 库都提供文档的本地副本(包括 JavaDoc),使用 HTML 格式。在 Castor 中,这个路径是 castor-1.1.2.1/doc/。因此在我的系统中,我为 /usr/local/java/castor-1.1.2.1/doc/index.html添加了一个书签。图 3 显示了本地载入的 Castor 文档外观,版本为 1.1.2.1。
图 3. 本地载入的 Castor 文档
在本文中以及在您日常编程中都需要执行这些操作,原因有二:
文档是本地的。 在飞机上编写过程序吗?是不是没有网络链接?不能登录到 Starbucks WiFi 吧?本地文档除了能够更快速地访问之外,在这些情形中也发挥着重要作用。
本地文档总是适合您自己的需要。随着 Castor 的不断发展,您也许不会经常下载最新的发行版。使用在线文档就意味着使用最新版本的文档,这可能与您系统中的版本不匹配。当使用本地文档时,使用的文档总是和当前使用的库版本对应。因此,不会由于使用不恰当或者库版本中根本不存在的特性而引起混乱和挫折。
下载 Castor 依赖项
Castor 有许多依赖项:
Apache Ant
Jakarta Commons
JDBC 2.0 Standard Extensions
Log4J 登录实用程序
Apache Xerces XML 解析程序
这实际上是适用于大多数 Castor 操作的一个精简的集合。如果想从头构建 Castor、运行这些示例、使用这些测试,或者更深入地研究 Castor,还需要更多的依赖项。必须将这些依赖项放到类路径中,才能使用 Castor。
复杂的方法
要运行 Castor,比较麻烦的方法就是,首先访问 Castor 的下载页面并记下所需的每个依赖项的版本。然后跳转到每个依赖项的 Web 站点,找到该版本,下载并将其添加到类路径中。这种方法会花费较长的时间,但是更加易于控制。此外,如果您已经设置好并能正常运行大多数库,这仍然是一个可行的方法。
简单的方法
幸运的是,还有一种更好的方法。回到 Castor 的下载页面,找到稳定版本,并定位到另一个下载套件,这个下载套件叫做
Full SVN snapshot: All sources, docs, and 3rd party libraries (big)。尽管标记为 “big”,但只有 10 MB(对于用 DSL 或者电缆上网的用户来说,这根本不算什么)。下载这个文件,并展开(如图 4 所示)。
图 4. Full SVN 截图(已展开)
现在可以进入 lib/目录了,其中包含大量的 JAR 文件。这些正是 Castor 所需的库。
存放更多库的位置
创建一个新目录 —在最初的 Castor 安装目录中或者与之同级的目录 —然后将刚才下载的所有 JAR 文件移动到这个目录中。例如:
[bmclaugh:~] cd /usr/local/java
[bmclaugh:/usr/local/java] ls
castor-1.1.2.1 xalan-j_2_7_0
[bmclaugh:/usr/local/java] cd castor-1.1.2.1/
[bmclaugh:/usr/local/java/castor-1.1.2.1] ls
CHANGELOG castor-1.1.2.1.jar
castor-1.1.2.1-anttasks.jar doc
castor-1.1.2.1-codegen.jar jdbc-se2.0.jar
castor-1.1.2.1-ddlgen.jar jta1.0.1.jar
castor-1.1.2.1-jdo.jar schema
castor-1.1.2.1-xml.jar
[bmclaugh:/usr/local/java/castor-1.1.2.1] mkdir lib
[bmclaugh:/usr/local/java/castor-1.1.2.1] cd lib
[bmclaugh:/usr/local/java/castor-1.1.2.1/lib] cp ~/downloads/castor-1.1.2.1/lib/*.jar .
[bmclaugh:/usr/local/java/castor-1.1.2.1/lib]
此处,我在 Castor 文件夹中创建了一个 lib/目录,将所有的 JAR 文件移到其中,供 Castor 使用。
设置类路径
只包含 XML JAR 文件
在本文中,我主要讨论了如何运行 Castor,尤其是 XML 编组和解组处理。所以我只列出了实现这个功能所需的 JAR 文件。在后续文章中,您将会了解更多的 Castor 特性,我也会提及实现这些特性所需的其他 JAR 文件。
现在需要设置类路径中的所有东西。我在 Mac OS X 配置中使用一个 .profile文件处理所有这些问题。您也许想将您的 profile 也设置为这样,或者在 Windows 中设置一个系统环境变量。在任何情况下,都需要将如下 JAR 文件添加到类路径:
castor-1.1.2.1.jar(在 Castor 主目录中)
castor-1.1.2.1-xml.jar(在 Castor 主目录中)
xerces-J-1.4.0.jar(放在与 Castor 依赖项库相同的位置)
commons-logging-1.1.jar(放在与 Castor 依赖项库相同的位置)
作为参考,以下是我的 .profile,从中可以看到我是如何设置的:
export JAVA_BASE=/usr/local/java
export JAVA_HOME=/Library/Java/Home
export XERCES_HOME=$JAVA_BASE/xerces-2_6_2
export XALAN_HOME=$JAVA_BASE/xalan-j_2_7_0
export CASTOR_HOME=$JAVA_BASE/castor-1.1.2.1
export EDITOR=vi
export CASTOR_CLASSES=$CASTOR_HOME/castor-1.1.2.1.jar:
$CASTOR_HOME/castor-1.1.2.1-xml.jar:
$CASTOR_HOME/lib/xerces-J_1.4.0.jar:
$CASTOR_HOME/lib/commons-logging-1.1.jar
export CVS_RSH=ssh
export PS1="[`whoami`:/w] "
export CLASSPATH=$XALAN_HOME/xalan.jar:$XALAN_HOME/xml-apis.jar:
$XALAN_HOME/xercesImpl.jar:
~/lib/mclaughlin-xml.jar:
$CASTOR_CLASSES:.
请确保将所有这些文件都放到了类路径中,接下来将做一个快速测试。
测试安装
首先构建一个非常简单的类,然后构建一个实用程序将其在 XML 和 Java 之间来回转换。这里并不会演示 Castor 的所有功能,而只是一个非常基本的测试。清单 1 显示了我将使用的一个 CD 类。输入这些源代码并保存为 CD.java(或者从 参考资料下载这些代码)。
清单 1. CD 类(用于测试)
package ibm.xml.castor;
import java.util.ArrayList;
import java.util.List;
/** A class to represent CDs */
public class CD implements java.io.Serializable {
/** The name of the CD */
private String name = null;
/** The artist of the CD */
private String artist = null;
/** Track listings */
private List tracks = null;
/** Required no-args constructor */
public CD() {
super();
}
/** Create a new CD */
public CD(String name, String artist) {
super();
this.name = name;
this.artist = artist;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setArtist(String artist) {
this.artist = artist;
}
public String getArtist() {
return artist;
}
public void setTracks(List tracks) {
this.tracks = tracks;
}
public List getTracks() {
return tracks;
}
public void addTrack(String trackName) {
if (tracks == null) {
tracks = new ArrayList();
}
tracks.add(trackName);
}
}
现在需要一个类处理编组。如清单 2 所示。
清单 2. 用于测试编组的类
package ibm.xml.castor;
import java.io.FileWriter;
import org.exolab.castor.xml.Marshaller;
public class MarshalTester {
public static void main(String[] args) {
try {
CD sessions = new CD("Sessions for Robert J", "Eric Clapton");
sessions.addTrack("Little Queen of Spades");
sessions.addTrack("Terraplane Blues");
FileWriter writer = new FileWriter("cds.xml");
Marshaller.marshal(sessions, writer);
} catch (Exception e) {
System.err.println(e.getMessage());
e.printStackTrace(System.err);
}
}
}
最后一个类如清单 3 所示,是一个用于解组的类。
清单 3. 用于测试解组的类
package ibm.xml.castor;
import java.io.FileReader;
import java.util.Iterator;
import java.util.List;
import org.exolab.castor.xml.Unmarshaller;
public class UnmarshalTester {
public static void main(String[] args) {
try {
FileReader reader = new FileReader("cds.xml");
CD cd = (CD)Unmarshaller.unmarshal(CD.class, reader);
System.out.println("CD title: " + cd.getName());
System.out.println("CD artist: " + cd.getArtist());
List tracks = cd.getTracks();
if (tracks == null) {
System.out.println("No tracks.");
} else {
for (Iterator i = tracks.iterator(); i.hasNext(); ) {
System.out.println("Track: " + i.next());
}
}
} catch (Exception e) {
System.err.println(e.getMessage());
e.printStackTrace(System.err);
}
}
}
像下面这样编译这些类:
[bmclaugh:~/Documents/developerworks/castor] javac -d . *.java
Note: CD.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
如果使用的是 Java 5 或更高的版本,而在 CD.java中没有使用参数化的类型,就会出现上面的警告。不要担心,这不会有什么影响。现在需要运行编组程序测试类。
[bmclaugh:~/Documents/developerworks/castor] java ibm.xml.castor.MarshalTester
找到并打开 cds.xml。其内容应该像这样:
Eric Clapton
Sessions for Robert J
xsi:type="java:java.lang.String">Little Queen of Spades
xsi:type="java:java.lang.String">Terraplane Blues
这些内容可读性不太好,但是应该能在 XML 文档中看到在 MarshalTester类中创建的 CD 的所有信息。
现在需要确保可以将 XML 文档转换回 Java。运行解组测试程序:
[bmclaugh:~/Documents/developerworks/castor] java ibm.xml.castor.UnmarshalTester
CD title: Sessions for Robert J
CD artist: Eric Clapton
Track: Little Queen of Spades
Track: Terraplane Blues
这些代码非常简单,无需解释。如果你获得了这样的输出,就说明已经用 Castor 打开了 XML 文件,并且已经将其转换为一个 Java 类。
现在 —我们假设您已经用 UnmarshalTester获得了相同的 cds.xml和输出 —您安装的 Castor 能够正常运行。您还没有使用 Castor 做任何比较复杂的工作,只是确保了它能正常运行、正确设置了 JAR 文件以及 Castor 能够根据需要实现不同的功能。
本文转自
http://www.ibm.com/developerworks/cn/xml/x-xjavacastor1/