级别: 高级 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 解组为满足最低要求的任何类:
- 类名为 “Book”(使用映射文件可以改变,但这一点后面再说)。
- 这个类包括三个字段:
authorName、title 和 isbn。
仅此而已!看看能否编写满足这些要求的几个类,并改变类的其他 字段或者包声明、方法……很快您就会发现这种方法使得 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 同样能办到。它说明了如何同时编组 Book 和 Author 类(再看看 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 不需要了解很多就能实例化类。但是,它还要求类必须能通过不带参数的构造器实例化。
好消息是 Book 和 Author 类只需简单修改就能避免这些错误。只需要为两个类增加不带参数的构造器,public Book() { } 和 public Author() { }。重新编译并运行代码。
想想这意味着什么。有了无参数的构造器,不仅仅是 Castor,任何 类或者程序都能创建类的新实例。对于图书和作者来说,可以创建没有 ISBN、标题和作者的图书,或者没有姓和名的作者 — 这肯定会造成问题。如果 Castor 没有更先进的特性(下一期再讨论)这种缺陷就不可避免,因此必须非常注意类的使用。还必须考虑为任何可能造成 NullPointerException 错误的数据类型设置具体的值(字符串可以设为空串或者默认值,对象必须初始化等等)。
第二步:null 引起的更多问题
为 Book 和 Author 类增加无参数构造器,重新运行解组器。结果如下:
清单 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() 方法就无法设置字段的值。因此需要为 Book 和 Author 类增加一些方法。下面是需要添加的方法(实现很简单,留给读者自己完成):
-
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 方法。
代价是值得的
现在的类和最初相比没有很大变化。Book 和 Author 没有面目全非,功能上没有很大不同(实际上没有什么区别)。但是现在设计还有一点问题。图书必须 有 ISBN(至少在我看来),因此能够创建没有 ISBN 的图书 — 无参数构造器 — 令我感到困扰。此外,我也不愿意别人随便改动图书的 ISBN,这样不能正确地表示图书对象。
作者的修改不那么严重,因为对于作者这个对象来说姓名可能不是很重要的标识符。名字可以改,现在甚至姓都可以改。另外,两位作者如果同名,目前也没有区分的现成办法。但即使增加了更具唯一性、更合适的标识符(社会安全号码、驾驶证号、其他标识符),仍然需要无参数构造器和字段 setter 方法。因此问题仍然存在。
这就变成了效益和控制的问题:
- Castor 是否提供了足够的好处 — 简化数据绑定 — 足以抵得上设计所要做出的让步?
- 对代码库是否有足够的控制权,避免滥用为 Castor 增加的方法?
只有您才能代表您的企业回答这些问题。对于多数开发人员来说,权衡的结果倾向于 Castor,就必须做出适当的让步。对于那些沉醉于设计或者由于特殊需求无法做出这些让步的少数人,可能更愿意自己编写简单的 XML 序列化工具。无论如何,应该将 Castor 放到您的工具包里。如果它不适合当前的项目,也许下一个用得上。
结束语
到目前为止还没有提到的 Castor 的一大特性是映射文件。我们是直接从 Java 代码翻译成 XML。但是有几个假定:
- 需要把 Java 类中的所有字段持久到 XML。
- 需要在 XML 中保留类名和字段名。
- 有一个类模型和需要反序列化的 XML 文档中的数据匹配。
对于企业级编程,这些假定都有可能不成立。如果将字段名和类名存储到 XML 文档中被认为是一种安全风险,可能会过多泄露应用程序的结构,该怎么办?如果交给您一个 XML 文档需要转化成 Java 代码,但希望使用不同的方法名称和字段名称,怎么办?如果只需要少数类属性存储到 XML 中,怎么办?
所有这些问题的答案都是一个:Castor 提供了进一步控制 Java 代码和 XML 之间映射关系的方式。下一期文章我们将详细介绍映射。现在,不要只考虑编组和解组,还要花时间想想为了让 Castor 正常工作所作的那些修改意味着什么。在思考的同时,不要忘记回来看看下一期文章。到时候再见。
下载 | 描述 | 名字 | 大小 | 下载方法 |
|---|
| 本文的 Java 源代码 | x-xjavacastor2/castor2_source_code.zip | 2KB | HTTP |
|---|
| 本文经过编译的 Java 代码 | x-xjavacastor2/castor2_compiled_code.zip | 4KB | HTTP |
|---|
参考资料 学习
获得产品和技术
讨论
关于作者  | 
|  | Brett McLaughlin 的著作上过畅销榜并获得过非小说类图书奖。他著述丰富,包括计算机编程、家庭暴力、分析和设计,总印数超过 100,000。他编写、编辑和出版技术书籍快十年了,除了惬意地使用文字处理程序写书以外,他还喜欢弹奏吉他、和两个儿子在屋子里追逐嬉闹、和妻子观看重新开播的 Arrested Development。他的新著 Head First Object Oriented Analysis and Design 荣获 2007 Jolt Technical Book 大奖。经典著作 Java and XML 仍然是关于在 Java 语言中使用 XML 技术的权威书籍。 |
对本文的评价
|