级别: 初级 Brett McLaughlin (brett@oreilly.com), 作家兼编辑, O'Reilly and Associates
2002 年 12 月 01 日 在这篇技巧文章里,您将学到一种在 DOM 应用程序中进行自举的更好方法。本文以前一篇技巧文章为基础,那篇文章讨论了 DOM 本身能为自举任务做些什么。
在
前一篇技巧文章 中,我解释了 DOM 自举的基础知识,并特别解释了使用 DOM 级别 1 或 2 时这些基础知识将如何付诸实现。您学会了如何获取
DOMImplementation 类的供应商实现,以及如何用它来生成
Document 和
DocumentType 对象。而且,最为重要的是,您了解了 DOM 提供的自举功能带来的各种问题。
作为一个简短的温习,在讨论这些问题的解决方案之前,我将概述这些问题:
- 产生了对特定解析器的依赖性
- 在许多情况下,产生了对特定解析器的特定
版本的依赖性
- 对 DOM 实现或解析器的更改需要进行代码级更改和重编译
-
对 DOM 实现的更改需要更改 CLASSPATH
在以上各个问题中,只有一个问题在生产环境中是确实可接受的 ― 也就是最后一个问题,
4,对应用程序的 CLASSPATH 的更改。其它三个限制都非常严重,它们会对您能否获得可重用的(有时是可重新销售的)应用程序造成影响。
如果您回忆以下,您就会想起前一篇技巧文章是以清单 1 中所显示的代码片段作为结束的。
清单 1. XMLReader 的解析入口点
DOMImplementation domImpl =
new org.apache.xerces.dom.DOMImplementationImpl();
DocumentType docType =
domImpl.createDocumentType("rootElementName", "public ID", "system ID");
Document doc = domImpl.createDocument("", "rootElementName", docType);
|
虽然这并不是一个差劲的自举解决方案,但它也并不特别优秀。我们不使用这种方法,也不接受它的限制,让我们来看一种更好的解决方案。在理想情况下,您需要能够从自举过程中除去所有特定于供应商的代码,并在应用程序外指定那个信息。
在理想情况下,您可以在代码中或在应用程序启动时设置系统特性(通过
java 过程的
-D 标志);我更愿意用
org.w3c.dom.DOMImplementationClass 作为该特性的名称。该特性的值是一个实现类,代码需要这一实现类来实例化
DOMImplementation 实例。在示例中,我一直使用 Apache Xerces,因此该特性的值为
org.apache.xerces.dom.DOMImplementationImpl 。
一旦您适当地掌握了这一基本思想,那么编写一个助手类就相当简单了,该助手类负责读入并实例化上述特性,然后将新对象返回给使 DOM 实例启动和运行所需的代码。清单 2 显示了这样一个助手类。
清单 2. 样本助手类
package com.ibm.xml;
import org.w3c.dom.Document;
import org.w3c.dom.DocumentType;
import org.w3c.dom.DOMImplementation;
public class DOMFactory {
/** System property name */
private static final String IMPL_PROPERTY_NAME =
"org.w3c.dom.DOMImplementationClass";
/** Initialization flag */
private static boolean initialized = false;
/** The DOMImplementation to use */
private static DOMImplementation domImpl;
private static void initialize() throws Exception {
domImpl =
(DOMImplementation)Class.forName(
System.getProperty(IMPL_PROPERTY_NAME)).newInstance();
initialized = true;
}
public static Document newDocument(String namespaceURI, String rootQName,
DocumentType docType)
throws Exception {
if (!initialized) {
initialize();
}
return domImpl.createDocument(namespaceURI, rootQName, docType);
}
public static DocumentType newDocumentType(String rootQName,
String publicId, String systemId)
throws Exception {
if (!initialized) {
initialize();
}
return domImpl.createDocumentType(rootQName, publicId, systemId);
}
}
|
上面的类实际上非常简单。该类的入口点是两个 public 方法,它们各返回两个 DOM
启动 类中的一个。这两个类是
DOMImplementation 生成的相同的两个类,因此这为您使用助手类提供了一些一致性。这两种方法都确保进行了初始化,然后生成所请求的对象。
初始化也并非那么复杂。系统特性返回一个类名(假定类名使用正确!),然后通过
Class.forName().newInstance() 机制实例化该类名。一旦上述处理完成,那么存储对象以及用它来生成对象就很容易了。
现在您得到了一种更好的自举方法!这一方法真得很简单。在您开始解析之前,只需将这个类连同所需的任何解析器 JAR 文件一起添加到您的类路径中,并且设置系统特性。甚至不用深究特定于供应商的代码,您就可以获得 DOM 类型。在 DOM 级别 3 公开发行以及更好的自举方法出现之前,它将一直助您克服困难,以顺利完成各种任务。还想了解其它知识吗?好!在下一篇技巧文章中,我将详细讨论如何设置 DOM 级别 3 以使之工作,并在自举方法的进展方面给你一个惊喜。到时候网上见!
参考资料
关于作者  | 
|  |
Brett McLaughlin自从 Logo 时代(还记得小三角形吗?)开始就一直从事计算机方面的工作。目前,他专门从事用 Java 语言和与 Java 相关的技术构建应用程序基础结构。最近几年,他在 Nextel Communications 和 Allegiance Telecom, Inc. 从事这些基础结构的实现。Brett 是 Java Apache Turbine 项目的共同创始人之一,该项目通过使用 Java servlet 为 Web 应用程序开发构建可重用的组件体系结构。他还是 EJBoss 项目(一种开放源码 EJB 应用程序服务器)和 Cocoon(一种开放源码 XML Web 发布引擎)的志愿开发人员之一。
|
对本文的评价
|