IBM®
跳转到主要内容
    中国 [选择]    使用条款
 
 
Select a scope:Search for:    
    首页    产品    服务与解决方案     支持与下载    个性化服务    
跳转到主要内容

developerWorks 中国  >  XML | Java technology  >

实现 Castor 数据绑定,第 2 部分: 编组和解组 XML

使用 Castor 进行 XML 数据绑定

developerWorks
文档选项

未显示需要 JavaScript 的文档选项

讨论

样例代码

英文原文

英文原文


级别: 高级

Brett D. McLaughlin, Sr. (brett@newInstance.com), 作家兼编辑, O'Reilly Media, Inc.

2007 年 12 月 27 日

本系列的上一期文章中,我们下载、安装和设置了 Castor。本文将介绍如何把 Java™ 类转化成 XML 然后再把 XML 转换回 Java 代码,以及 Castor 的工作原理,如何保证类的设计适应这种 API。

需要准备什么

开始之前需要保证具备了本文所需要的前提条件。确保满足这些要求最简单的办法就是按照 本系列第一篇文章(链接参见本文 参考资料 部分)介绍的步骤操作。第一篇文章介绍了如何下载、安装和配置 Castor,并用一些简单的类进行了测试。

从您手头的项目中选择一些类转换成 XML 然后再转换回来也没有问题。本文(以及上一期文章)提供了一些例子,但是要掌握 Castor,最好的办法是把这里学到的东西应用到您自己的项目中。首先从一些简单的对象类开始,比如代表人、唱片、图书或者某种其他具体对象的类。然后可以阅读本文中关于映射的内容,从而增加一些更复杂的类。





回页首


编组 101

Castor 最基本的操作是取一个 Java 类然后将类的实例编组成 XML。可以把类本身作为顶层容器元素。比如 Book 类很可能在 XML 文档中得到一个名为 “book” 的根元素。

类的每个属性也表示在 XML 文档中。因此值为 “Power Play” 的 title 属性将生成这样的 XML:

<title>Power Play</title>

很容易由此推出一个简单 Java 类所生成的 XML 文档的其余部分。





回页首


编组类的实例

开始编组代码之前有几点需要注意。第一,只能编组类的实例而不能编组类本身。类是一种结构,等同于 XML 约束模型,如 DTD 或 XML Schema。类本身没有数据,仅仅定义了所存储的数据的结构和访问方法。

实例化类(或者通过工厂以及其他实例生成机制获得)将赋予它具体的形式。然后用实际数据填充实例的字段。实例是惟一的,它和同一类的实例具有相同的结构,但数据是不同的。图 1 直观地说明了这种关系。


图 1. 类提供结构,实例即数据
类提供数据形式,实例填充数据

因而编组的只能是实例。后面将看到如何使用约束模型和映射文件改变 XML 的结构。但是现在要做的是让 XML 结构(元素和属性)和 Java 结构(属性)匹配。

基本的编组

清单 1 是本文中将使用的一个简单的 Book 类。


清单 1. Book 类
                package ibm.xml.castor;

public class Book {

 /** The book's ISBN */
 private String isbn;
 /** The book's title */
 private String title;
 /** The author's name */
 private String authorName;

 public Book(String isbn, String title, String authorName) {
 this.isbn = isbn;
 this.title = title;
 this.authorName = authorName;
 }

 public String getIsbn() {
 return isbn;
 }

 public void setTitle(String title) {
 this.title = title;
 }

 public String getTitle() {
 return title;
 }

 public void setAuthorName(String authorName) {
 this.authorName = authorName;
 }

 public String getAuthorName() {
 return authorName;
 }
}

编译上述代码将得到 Book.class 文件。这个类非常简单,只有三个属性:ISBN、标题和作者姓名(这里有些问题,暂时先不管)。仅仅这一个文件还不够,Castor 还需要几行代码将 Book 类的实例转化成 XML 文档。清单 2 中的小程序创建了一个新的 Book 实例并使用 Castor 转化成 XML。


清单 2. Book 编组器类
                package ibm.xml.castor;

import java.io.FileWriter;

import org.exolab.castor.xml.Marshaller;

public class BookMarshaller {

 public static void main(String[] args) {
 try {
 Book book = new Book("9780312347482", "Power Play", "Joseph Finder");
 FileWriter writer = new FileWriter("book.xml");
 Marshaller.marshal(book, writer);
 } catch (Exception e) {
 System.err.println(e.getMessage());
 e.printStackTrace(System.err);
 }
 }
}

编译然后运行该程序。将得到一个新文件 book.xml。打开该文件将看到如下所示的内容:


清单 3. 编译后的程序创建的 XML
                <?xml version="1.0" encoding="UTF-8"?>
<book><author-name>Joseph Finder</author-name>
<isbn>9780312347482</isbn><title>Power Play</title></book>

为了清晰起见我增加了断行。实际生成的 XML 文档在 author-name 元素的结束标记和 isbn 元素的开始标记之间没有断行。

Castor 遗漏了什么

在改进这个例子之前 — 很有必要改进— 先看看 Castor 在 XML 中漏掉 了什么:

  • Java 类的包。Java 包不属于类结构。这实际上是一个语义问题,和 Java 名称空间有关。因此可以将这个 XML 文档解组 — 从 XML 转换为 Java 代码 — 到任何具有相同的三个属性的 Book 实例,不论是什么包。
  • 字段顺序。这是 XML 的顺序问题,和 Java 编程无关。因此尽管源文件按某种顺序列出字段,但 XML 文档可能完全不同。这对于 XML 来说至关重要,但是和 Book 类声明无关。
  • 方法。和包声明一样,方法也和数据结构无关。因此 XML 文档没有涉及到这些方面,将其忽略了。

那么就要问 “那又怎么样呢?” 如果不重要,XML 忽略这些细节又有什么关系呢?但是这些信息 重要。之所以重要是因为它们提供了超出预想的更大的灵活性。可以将这些 XML 解组为满足最低要求的任何类:

  1. 类名为 “Book”(使用映射文件可以改变,但这一点后面再说)。
  2. 这个类包括三个字段:authorNametitleisbn

仅此而已!看看能否编写满足这些要求的几个类,并改变类的其他 字段或者包声明、方法……很快您就会发现这种方法使得 Castor 多么灵活。





回页首


添加更复杂的类型

Book 类最明显的不足是不能存储多个作者。修改类使其能处理多个作者也很容易:


清单 4. 存储多个作者的 Book 类
                package ibm.xml.castor;

import java.util.LinkedList;
import java.util.List;

public class Book {

 /** The book's ISBN */
 private String isbn;
 /** The book's title */
 private String title;
 /** The authors' names */
 private List authorNames;

 public Book(String isbn, String title, List authorNames) {
 this.isbn = isbn;
 this.title = title;
 this.authorNames = authorNames;
 }

 public Book(String isbn, String title, String authorName) {
 this.isbn = isbn;
 this.title = title;
 this.authorNames = new LinkedList();
 authorNames.add(authorName);
 }

 public String getIsbn() {
 return isbn;
 }

 public void setTitle(String title) {
 this.title = title;
 }

 public String getTitle() {
 return title;
 }

 public void setAuthorNames(List authorNames) {
 this.authorNames = authorNames;
 }

 public List getAuthorNames() {
 return authorNames;
 }

 public void addAuthorName(String authorName) {
 authorNames.add(authorName);
 }
}

如果使用 Java 5 或 6 技术,将会显示一些未检查/不安全操作的错误,因为这段代码没有使用参数化的 Lists。如果愿意可以自己增加这些代码。

这样的修改很简单,不需要对编组代码作任何修改。但是,有必要用一本多人编写的图书来验证 Castor 编组器能否处理集合。修改 BookMarshaller 类如下:


清单 5. 处理收集器的 Book 类
                package ibm.xml.castor;

import java.io.FileWriter;
import java.util.ArrayList;
import java.util.List;

import org.exolab.castor.xml.Marshaller;

public class BookMarshaller {

 public static void main(String[] args) {
 try {
 Book book = new Book("9780312347482", "Power Play", "Joseph Finder");
 FileWriter writer = new FileWriter("book.xml");
 Marshaller.marshal(book, writer);

 List book2Authors = new ArrayList();
 book2Authors.add("Douglas Preston");
 book2Authors.add("Lincoln Child");
 Book book2 = new Book("9780446618502", "The Book of the Dead",
 book2Authors);
 writer = new FileWriter("book2.xml");
 Marshaller.marshal(book2, writer);

 } catch (Exception e) {
 System.err.println(e.getMessage());
 e.printStackTrace(System.err);
 }
 }
}

第一本书的处理方式没有变,重新打开 book.xml 将看到和原来相同的结果。打开 book2.xml 看看 Castor 如何处理集合:


清单 6. 带有收集器的 XML 结果
                <?xml version="1.0" encoding="UTF-8"?>
<book><isbn>9780446618502</isbn><title>The Book of the Dead</title>
<author-names xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xsi:type="java:java.lang.String">Douglas Preston</author-names>
<author-names xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xsi:type="java:java.lang.String">Lincoln Child</author-names>
</book>

显然,Castor 处理作者姓名列表没有问题。更重要的是,Castor 不仅为作者名称创建了一个 blanket 容器,这个框架实际上看到了列表的内部,并认识到内容是字符串(要记住,这不是参数化列表,Castor 必须自己确定列表成员的类型)。因此 XML 进行了一些非常具体的类型化工作。这是个不错的特性,尤其是如果需要将 XML 转化回 Java 代码之前进行一些处理的话。





回页首


添加自定义类

我们朝着真正实用的程序再前进一步。存储字符串作者姓名肯定最终会出现重复的数据(多数作者写了不只一本书)。清单 7 增加了一个新的类 Author


清单 7. Author 类
                package ibm.xml.castor;

public class Author {

 private String firstName, lastName;
 private int totalSales;

 public Author(String firstName, String lastName) {
 this.firstName = firstName;
 this.lastName = lastName;
 }

 public String getFirstName() {
 return firstName;
 }

 public String getLastName() {
 return lastName;
 }

 public void setTotalSales(int totalSales) {
 this.totalSales = totalSales;
 }

 public void addToSales(int additionalSales) {
 this.totalSales += additionalSales;
 }

 public int getTotalSales() {
 return totalSales;
 }
}

是不是很简单?在 Book 类的下面作上述修改以便能够使用新的 Author 类。


清单 8. 使用自定义作者类的 Book 类
                package ibm.xml.castor;

import java.util.LinkedList;
import java.util.List;

public class Book {

 /** The book's ISBN */
 private String isbn;
 /** The book's title */
 private String title;
 /** The authors' names */
 private List authors;

 public Book(String isbn, String title, List authors) {
 this.isbn = isbn;
 this.title = title;
 this.authors = authors;
 }

 public Book(String isbn, String title, Author author) {
 this.isbn = isbn;
 this.title = title;
 this.authors = new LinkedList();
 authors.add(author);
 }

 public String getIsbn() {
 return isbn;
 }

 public void setTitle(String title) {
 this.title = title;
 }

 public String getTitle() {
 return title;
 }

 public void setAuthors(List authors) {
 this.authors = authors;
 }

 public List getAuthors() {
 return authors;
 }

 public void addAuthor(Author author) {
 authors.add(author);
 }
}

测试上述代码需要对 BookMarshaller 略加修改:


清单 9. 增加了作者信息的 BookMarshaller 类
                package ibm.xml.castor;

import java.io.FileWriter;
import java.util.ArrayList;
import java.util.List;

import org.exolab.castor.xml.Marshaller;

public class BookMarshaller {

 public static void main(String[] args) {
 try {
 Author finder = new Author("Joseph", "Finder");
 Book book = new Book("9780312347482", "Power Play", finder);
 FileWriter writer = new FileWriter("book.xml");
 Marshaller.marshal(book, writer);

 List book2Authors = new ArrayList();
 book2Authors.add(new Author("Douglas", "Preston"));
 book2Authors.add(new Author("Lincoln", "Child"));
 Book book2 = new Book("9780446618502", "The Book of the Dead",
 book2Authors);
 writer = new FileWriter("book2.xml");
 Marshaller.marshal(book2, writer);

 } catch (Exception e) {
 System.err.println(e.getMessage());
 e.printStackTrace(System.err);
 }
 }
}

仅此而已!编译然后运行编组器。看看两个结果文件,这里仅列出 book2.xml,因为这个文件更有趣一点。


清单 10. 包括作者和图书信息的 XML 结果
                <?xml version="1.0" encoding="UTF-8"?>
<book><authors xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
total-sales="0" xsi:type="java:ibm.xml.castor.Author"><last-name>Preston</last-name>
<first-name>Douglas</first-name></authors><authors 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" total-sales="0"
 xsi:type="java:ibm.xml.castor.Author"><last-name>Child</last-name>
<first-name>Lincoln</first-name></authors><isbn>9780446618502</isbn>
<title>The Book of the Dead</title></book>

Castor 同样能办到。它说明了如何同时编组 BookAuthor 类(再看看 authors 列表)。Castor 甚至为 Author 增加了 totalSales 属性,可以试试看结果如何。

Castor 对泛型的处理

也许听起来像是全天候的推销频道,但 Castor 确实支持泛型和参数化列表。因此如果习惯 Java 5 或 Java 6,可以这样修改 Book


清单 11. 处理泛型和参数化列表的 Book 类
                package ibm.xml.castor;

import java.util.LinkedList;
import java.util.List;

public class Book {

 /** The book's ISBN */
 private String isbn;
 /** The book's title */
 private String title;
 /** The authors' names */
 private List<Author> authors;

 public Book(String isbn, String title, List<Author> authors) {
 this.isbn = isbn;
 this.title = title;
 this.authors = authors;
 }

 public Book(String isbn, String title, Author author) {
 this.isbn = isbn;
 this.title = title;
 this.authors = new LinkedList<Author>();
 authors.add(author);
 }

 public String getIsbn() {
 return isbn;
 }

 public void setTitle(String title) {
 this.title = title;
 }

 public String getTitle() {
 return title;
 }

 public void setAuthors(List<Author> authors) {
 this.authors = authors;
 }

 public List<Author> getAuthors() {
 return authors;
 }

 public void addAuthor(Author author) {
 authors.add(author);
 }
}

这样作者列表就 接受 Author 实例了,这是一个非常重要的改进。可以对 BookMarshaller 作类似的修改,重新编译,并得到相同的 XML 输出。换句话说,可以为 Castor 建立非常具体的类。

类变了但 Castor 没有变

在最终讨论解组之前,还需要做一项重要的观察。前面对类作的所有修改都没有改变编组代码!我们增加了泛型、自定义类、集合等等,但是编组 XML,Castor API 只需要一次简单的调用。太令人吃惊了!





回页首


解组

花了很多时间详细讨论完编组以后,解组非常简单。有了 XML 文档,并保证具有和数据匹配的 Java 类之后,剩下的工作交给 Castor 就行了。我们来解组前面生成的两个 XML 文档。如清单 12 所示。


清单 12. 解组图书
                package ibm.xml.castor;

import java.io.FileReader;
import java.util.Iterator;
import java.util.List;

import org.exolab.castor.xml.Unmarshaller;

public class BookUnmarshaller {

 public static void main(String[] args) {
 try {
 FileReader reader = new FileReader("book.xml");
 Book book = (Book)Unmarshaller.unmarshal(Book.class, reader);
 System.out.println("Book ISBN: " + book.getIsbn());
 System.out.println("Book Title: " + book.getTitle());
 List authors = book.getAuthors();
 for (Iterator i = authors.iterator(); i.hasNext(); ) {
 Author author = (Author)i.next();
 System.out.println("Author: " + author.getFirstName() + " " +
 author.getLastName());
 }

 System.out.println();

 reader = new FileReader("book2.xml");
 book = (Book)Unmarshaller.unmarshal(Book.class, reader);
 System.out.println("Book ISBN: " + book.getIsbn());
 System.out.println("Book Title: " + book.getTitle());
 authors = book.getAuthors();
 for (Iterator i = authors.iterator(); i.hasNext(); ) {
 Author author = (Author)i.next();
 System.out.println("Author: " + author.getFirstName() + " " +
 author.getLastName());
 }
 } catch (Exception e) {
 System.err.println(e.getMessage());
 e.printStackTrace(System.err);
 }
 }
}

编译代码并运行。您可能会得到意料之外的结果!我遇到的错误和堆栈记录如下所示:


清单 13. 解组遇到的错误和堆栈记录
                [bmclaugh:~/Documents/developerworks/castor-2] 
java ibm.xml.castor.BookUnmarshaller
ibm.xml.castor.Book
org.exolab.castor.xml.MarshalException: ibm.xml.castor.Book{File:
 [not available]; line: 2; column: 7}
 at org.exolab.castor.xml.Unmarshaller.
 convertSAXExceptionToMarshalException(Unmarshaller.java:755)
 at org.exolab.castor.xml.Unmarshaller.unmarshal 
(Unmarshaller.java:721)
 at org.exolab.castor.xml.Unmarshaller.unmarshal 
(Unmarshaller.java:610)
 at org.exolab.castor.xml.Unmarshaller.unmarshal 
(Unmarshaller.java:812)
 at ibm.xml.castor.BookUnmarshaller.main 
(BookUnmarshaller.java:14)
Caused by: java.lang.InstantiationException: ibm.xml.castor.Book
 at java.lang.Class.newInstance0(Class.java:335)
 at java.lang.Class.newInstance(Class.java:303)
 at org.exolab.castor.util.DefaultObjectFactory.createInstance(
 DefaultObjectFactory.java:107)
 at org.exolab.castor.xml.UnmarshalHandler.createInstance(
 UnmarshalHandler.java:2489)
 at org.exolab.castor.xml.UnmarshalHandler.startElement(
 UnmarshalHandler.java:1622)
 at org.exolab.castor.xml.UnmarshalHandler.startElement(
 UnmarshalHandler.java:1353)
 at org.apache.xerces.parsers.AbstractSAXParser.startElement 
(Unknown Source)
 at org.apache.xerces.impl.dtd.XMLDTDValidator.startElement 
(Unknown Source)
 at 
org.apache.xerces.impl.XMLDocumentFragmentScannerImpl.scanStartElement(
 Unknown Source)
 at org.apache.xerces.impl.XMLDocumentScannerImpl 
$ContentDispatcher.
 scanRootElementHook(Unknown Source)
 at org.apache.xerces.impl.
 XMLDocumentFragmentScannerImpl 
$FragmentContentDispatcher.dispatch(
 Unknown Source)
 at 
org.apache.xerces.impl.XMLDocumentFragmentScannerImpl.scanDocument(
 Unknown Source)
 at org.apache.xerces.parsers.XML11Configuration.parse 
(Unknown Source)
 at org.apache.xerces.parsers.XML11Configuration.parse 
(Unknown Source)
 at org.apache.xerces.parsers.XMLParser.parse(Unknown Source)
 at org.apache.xerces.parsers.AbstractSAXParser.parse(Unknown 
Source)
 at org.exolab.castor.xml.Unmarshaller.unmarshal 
(Unmarshaller.java:709)
 ... 3 more
Caused by: java.lang.InstantiationException: ibm.xml.castor.Book
 at java.lang.Class.newInstance0(Class.java:335)
 at java.lang.Class.newInstance(Class.java:303)
 at org.exolab.castor.util.DefaultObjectFactory.createInstance(
 DefaultObjectFactory.java:107)
 at org.exolab.castor.xml.UnmarshalHandler.createInstance(
 UnmarshalHandler.java:2489)
 at org.exolab.castor.xml.UnmarshalHandler.startElement 
(UnmarshalHandler.java:1622)
 at org.exolab.castor.xml.UnmarshalHandler.startElement 
(UnmarshalHandler.java:1353)
 at org.apache.xerces.parsers.AbstractSAXParser.startElement 
(Unknown Source)
 at org.apache.xerces.impl.dtd.XMLDTDValidator.startElement 
(Unknown Source)
 at 
org.apache.xerces.impl.XMLDocumentFragmentScannerImpl.scanStartElement(
 Unknown Source)
 at org.apache.xerces.impl.XMLDocumentScannerImpl 
$ContentDispatcher.
 scanRootElementHook(Unknown Source)
 at org.apache.xerces.impl.
 XMLDocumentFragmentScannerImpl 
$FragmentContentDispatcher.dispatch(
 Unknown Source)
 at 
org.apache.xerces.impl.XMLDocumentFragmentScannerImpl.scanDocument(
 Unknown Source)
 at org.apache.xerces.parsers.XML11Configuration.parse 
(Unknown Source)
 at org.apache.xerces.parsers.XML11Configuration.parse 
(Unknown Source)
 at org.apache.xerces.parsers.XMLParser.parse(Unknown Source)
 at org.apache.xerces.parsers.AbstractSAXParser.parse(Unknown 
Source)
 at org.exolab.castor.xml.Unmarshaller.unmarshal 
(Unmarshaller.java:709)
 at org.exolab.castor.xml.Unmarshaller.unmarshal 
(Unmarshaller.java:610)
 at org.exolab.castor.xml.Unmarshaller.unmarshal 
(Unmarshaller.java:812)
 at ibm.xml.castor.BookUnmarshaller.main 
(BookUnmarshaller.java:14)

那么到底是怎么回事呢?您遇到了直接使用 Castor 进行数据绑定必须要做出的几个让步中的第一个。

Castor 要求使用无参数的构造器

Castor 主要通过反射和调用 Class.forName(类名).newInstance() 这样的方法进行解组,因而 Castor 不需要了解很多就能实例化类。但是,它还要求类必须能通过不带参数的构造器实例化。

好消息是 BookAuthor 类只需简单修改就能避免这些错误。只需要为两个类增加不带参数的构造器,public Book() { }public Author() { }。重新编译并运行代码。

想想这意味着什么。有了无参数的构造器,不仅仅是 Castor,任何 类或者程序都能创建类的新实例。对于图书和作者来说,可以创建没有 ISBN、标题和作者的图书,或者没有姓和名的作者 — 这肯定会造成问题。如果 Castor 没有更先进的特性(下一期再讨论)这种缺陷就不可避免,因此必须非常注意类的使用。还必须考虑为任何可能造成 NullPointerException 错误的数据类型设置具体的值(字符串可以设为空串或者默认值,对象必须初始化等等)。

第二步:null 引起的更多问题

BookAuthor 类增加无参数构造器,重新运行解组器。结果如下:


清单 14. 添加无参数构造器后的结果
                [bmclaugh:~/Documents/developerworks/castor-2] java ibm.xml.castor.BookUnmarshaller
Book ISBN: null
Book Title: Power Play
Author: null null

Book ISBN: null
Book Title: The Book of the Dead
Author: null null
Author: null null

看来还有问题没解决(不是说解组很简单吗?先等等,后面还要说)。值得注意的是,有几个字段为空。把这些字段和 XML 比较,会发现这些字段在 XML 文档都有正确的表示。那么是什么原因呢?

为了找出根源,首先注意图书的标题 设置正确。此外仔细观察第二本书 The Book of the Dead。虽然初看起来似乎两本书的作者都没有设置,但问题不在这里。事实上,第二本书正确引用了两个 Author 对象。因此它引用了这两个对象,但是这些对象本身没有设置姓和名。因此图书的标题设置了,作者也一样。但是 ISBN 是空的,作者的姓和名也是空的。这是另一条线索:如果显示作者图书的总销售量,这些值就不会 是空。

发现了吗?空值字段都没有 setter(或 mutator)方法。没有 setIsbn()setFirstName() 等等。这是因为类被设计成需要构造信息(一旦书有了自己的 ISBN,这个 ISBN 实际上就不能改变了,基本上就意味着一本书形成了,因此最好要求构造/实例化新图书的时候提供新的 ISBN)。

还记得吗?Castor 使用反射机制。恰恰因为只有对象提供无参数构造器的时候它才能创建对象,因为没有 setFieldName() 方法就无法设置字段的值。因此需要为 BookAuthor 类增加一些方法。下面是需要添加的方法(实现很简单,留给读者自己完成):

  • setIsbn(String isbn)Book 类)
  • setFirstName(String firstName)Author 类)
  • setLastName(String lastName)Author 类)

增加上述方法之后重新编译就行了。

第三步:成功解组

再次尝试运行解组器,将得到如下所示的结果:


清单 15. 增加作者和 ISBN setter 方法后的解组结果
                [bmclaugh:~/Documents/developerworks/castor-2] java ibm.xml.castor.BookUnmarshaller
Book ISBN: 9780312347482
Book Title: Power Play
Author: Joseph Finder

Book ISBN: 9780446618502
Book Title: The Book of the Dead
Author: Douglas Preston
Author: Lincoln Child

终于得到了我们需要的结果。必须对类作几方面的修改。但是前面我曾提到解组非常简单。但是这和上面的情况不符,解组不是需要对类作很多修改吗?

实际上的确很简单。修改都是在您的类中,而和 Castor 解组过程无关。Castor 用起来非常简单,只要类的结构符合 Castor 的要求 — 每个类都要有无参数构造器,每个字段都要有 get/set 方法。





回页首


代价是值得的

现在的类和最初相比没有很大变化。BookAuthor 没有面目全非,功能上没有很大不同(实际上没有什么区别)。但是现在设计还有一点问题。图书必须 有 ISBN(至少在我看来),因此能够创建没有 ISBN 的图书 — 无参数构造器 — 令我感到困扰。此外,我也不愿意别人随便改动图书的 ISBN,这样不能正确地表示图书对象。

作者的修改不那么严重,因为对于作者这个对象来说姓名可能不是很重要的标识符。名字可以改,现在甚至姓都可以改。另外,两位作者如果同名,目前也没有区分的现成办法。但即使增加了更具唯一性、更合适的标识符(社会安全号码、驾驶证号、其他标识符),仍然需要无参数构造器和字段 setter 方法。因此问题仍然存在。

这就变成了效益和控制的问题:

  1. Castor 是否提供了足够的好处 — 简化数据绑定 — 足以抵得上设计所要做出的让步?
  2. 对代码库是否有足够的控制权,避免滥用为 Castor 增加的方法?

只有您才能代表您的企业回答这些问题。对于多数开发人员来说,权衡的结果倾向于 Castor,就必须做出适当的让步。对于那些沉醉于设计或者由于特殊需求无法做出这些让步的少数人,可能更愿意自己编写简单的 XML 序列化工具。无论如何,应该将 Castor 放到您的工具包里。如果它不适合当前的项目,也许下一个用得上。





回页首


结束语

到目前为止还没有提到的 Castor 的一大特性是映射文件。我们是直接从 Java 代码翻译成 XML。但是有几个假定:

  1. 需要把 Java 类中的所有字段持久到 XML。
  2. 需要在 XML 中保留类名和字段名。
  3. 有一个类模型和需要反序列化的 XML 文档中的数据匹配。
分享这篇文章……

digg 提交到 Digg
del.icio.us 发布到 del.icio.us
Slashdot 提交到 Slashdot!

对于企业级编程,这些假定都有可能不成立。如果将字段名和类名存储到 XML 文档中被认为是一种安全风险,可能会过多泄露应用程序的结构,该怎么办?如果交给您一个 XML 文档需要转化成 Java 代码,但希望使用不同的方法名称和字段名称,怎么办?如果只需要少数类属性存储到 XML 中,怎么办?

所有这些问题的答案都是一个:Castor 提供了进一步控制 Java 代码和 XML 之间映射关系的方式。下一期文章我们将详细介绍映射。现在,不要只考虑编组和解组,还要花时间想想为了让 Castor 正常工作所作的那些修改意味着什么。在思考的同时,不要忘记回来看看下一期文章。到时候再见。






回页首


下载

描述名字大小下载方法
本文的 Java 源代码x-xjavacastor2/castor2_source_code.zip2KBHTTP
本文经过编译的 Java 代码x-xjavacastor2/castor2_compiled_code.zip4KBHTTP
关于下载方法的信息


参考资料

学习
  • 您可以参阅本文在 develperWorks 全球网站上的 英文原文

  • 实现 Castor 数据绑定,第 1 部分: 安装和设置 Castor(Brett McLaughlin,developerWorks,2007 年 11 月):本系列的第一期文章介绍了如何下载、安装、设置、配置 Castor 以及类路径问题等等,以便在您的机器上运行它。

  • Castor Web 站点:访问关于 Castor 的所有在线资源。

  • Castor 类:查阅 JavaDoc。

  • xml.com:如果您还不熟悉 XML,这里有关于 XML 的各种资源。

  • Castor JDO 入门(Bruce Snyder,developerWorks,2002 年 10 月):阅读这篇早期的 developerWorks 文章。尽管文中的一些代码已经过时,但是其中的概念仍然适用。

  • 实用数据绑定: 涉入现实世界(Brett McLaughlin,developerWorks,2004 年 5 月):从共分多部分的系列文章入手,介绍了关于 Sun 的数据绑定 API 和 JAXB。

  • IBM XML 认证:了解如何才能成为一名 IBM 认证的 XML 及相关技术的开发人员。

  • XML 技术文档库:查看 developerWorks XML 专区提供的广泛的技术文章、技巧、教程、标准和 IBM 红皮书。

  • developerWorks 技术活动和网络广播:随时关注技术的最新进展。

  • 技术书店:浏览关于这些或其他技术主题的图书。


获得产品和技术
  • Java and XML, Third Edition(Brett McLaughlin 和 Justin Edelson,O'Reilly Media, Inc.):这本书全面介绍了 XML,包括关于数据绑定和映射的大量信息。

  • Java and XML Data Binding(Brett McLaughlin,O'Reilly Media, Inc.):在这部早期的著作中可以找到 Castor 的一些详细信息,以及数据绑定涉及的概念。

  • Castor Professional Services:正在寻求关于 Castor 的付费支持或帮助吗?请了解一下 Castor 的专业服务。

  • IBM 试用版软件:使用试用版软件构建下一个开发项目,这些软件可直接从 developerWorks 下载。


讨论


关于作者

Photo of Brett McLaughlin

Brett McLaughlin 的著作上过畅销榜并获得过非小说类图书奖。他著述丰富,包括计算机编程、家庭暴力、分析和设计,总印数超过 100,000。他编写、编辑和出版技术书籍快十年了,除了惬意地使用文字处理程序写书以外,他还喜欢弹奏吉他、和两个儿子在屋子里追逐嬉闹、和妻子观看重新开播的 Arrested Development。他的新著 Head First Object Oriented Analysis and Design 荣获 2007 Jolt Technical Book 大奖。经典著作 Java and XML 仍然是关于在 Java 语言中使用 XML 技术的权威书籍。




对本文的评价

太差! (1)
需提高 (2)
一般;尚可 (3)
好文章 (4)
真棒!(5)

将您的建议发给我们或者通过参加讨论与其他人分享您的想法.




回页首


IBM 公司保留在 developerWorks 网站上发表的内容的著作权。未经IBM公司或原始作者的书面明确许可,请勿转载。如果您希望转载,请通过 提交转载请求表单 联系我们的编辑团队。
    关于 IBM 隐私条约 联系 IBM 使用条款