以文本方式查看主题 - 中文XML论坛 - 专业的XML技术讨论区 (http://bbs.xml.org.cn/index.asp) -- 『 Java/Eclipse 』 (http://bbs.xml.org.cn/list.asp?boardid=41) ---- 代码生成方法 — JAXB 及其它(转贴) (http://bbs.xml.org.cn/dispbbs.asp?boardid=41&rootid=&id=8704) |
-- 作者:mfc42d -- 发布时间:7/9/2004 11:37:00 AM -- 代码生成方法 — JAXB 及其它(转贴) Java 中的 XML: 数据绑定,第 1 部分:代码生成方法 — JAXB 及其它 英文原文 内容: 回到绑定 数据和代码 JAXB 面前的漫漫长路 重新架构 JAXB JAXB beta 测试版 Castor JBind Quick Zeus 映射绑定 vs. 代码生成 结束语 参考资料 关于作者 对本文的评价 相关内容: Data binding with Castor Java 中 XML 文档模型的性能 Understanding SAX Understanding DOM 在 XML 和 Web 服务专区还有: 教学 工具与产品 所有的文章 根据 DTD 或模式生成数据类 级别:中级 Dennis M. Sosnoski(dms@sosnoski.com) 企业 Java 专家 Dennis Sosnoski 研究了几种 XML 数据绑定方法,这些方法根据用于 XML 文档的 W3C XML Schema 或 DTD 文法来生成代码。他从人们期待已久的 JAXB 标准(马上就要由 Java Community Process,JCP 发布了)入手,然后总结了其它一些目前可用的框架。最后,他讨论了如何以及何时以最佳方式将依据文法的代码生成应用到应用程序中。 除了简化编程之外,数据绑定还提供了其它一些好处。由于数据绑定对许多文档细节进行了抽象,因此对于在内存中处理文档,它通常所需要的内存比文档模型方法(譬如 DOM 或 JDOM)要少。您还会发现,由于不需要遍历文档结构以获取数据,因此用数据绑定方法访问程序内的数据要比用文档模型方法快。最后,在输入时,一些特殊类型的数据(譬如数字和日期)可以被转换成内部表示,而不是保留为文本形式;这使应用程序可以更有效地使用数据值。 您可能想知道,如果数据绑定有这么多的好处,那么何时使用文档模型方法呢?基本上在以下两种主要情形下需要用文档模型方法: 当应用程序确实要关注文档结构的细节时。例如,如果您正在编写一个 XML 文档编辑器,则您会希望采用文档模型,而不是使用数据绑定。 数据绑定字典 下面是一个微型字典,里面包含了我在本文中所使用的一些术语: 文法(Grammar)是用于定义一系列 XML 文档结构的一套规则。其中一类文法是 XML 规范所定义的文档类型定义(Document Type Definition,DTD)格式。另一类日渐普及的文法是 XML Schema 规范所定义的 W3C XML Schema(Schema)格式。文法定义了哪些元素和属性可以出现在文档中,以及在文档中元素是如何嵌套的(通常包括嵌套元素的次序和数目)。一些类型的文法(譬如 Schema)还可以更进一步,使字符数据内容与特定数据类型甚至正则表达式相匹配。在本文中,我会常使用术语描述, 将它作为引用一系列文档的文法的非正式方法。 编组(Marshalling)是在内存中为对象生成 XML 表示的过程。与 Java 对象序列化一样,这种表示需要包含所有依赖的对象:我们的主对象引用的对象、这些对象引用的对象等等。 数据分解(Unmarshalling)是与编组相反的过程,在内存中根据 XML 表示构建一个对象(而且可能是链接对象的图)。 这些框架各有优缺点,所以我会试图逐步指出每种框架所具有的最佳(和最差)特性。在第 2 部分,我将进一步向您显示这些框架如何对一些样本文档进行处理,另外,还将探讨,对于许多类型的应用程序,现有的数据绑定框架怎么会缺乏一些重要的特性。 相对于我在以前文章中所描述的映射绑定方法,根据 Schema 或 DTD 文法生成 Java 语言代码具有一些突出的优点。使用生成的代码,您可以确定数据对象被正确地链接到 XML 文档,不象映射绑定方法,需要直接指定链接,并确保正确地涵盖了所有的结构变体。在使用 Schema 时,甚至可以利用文法所提供的类型信息,用合适的数据类型来生成代码。 代码生成方法也有一些不足之处。这种方法造成应用程序数据结构与 XML 文档结构之间紧密耦合。另外,它还可能限定您使用简单的数据类(没有关联行为的被动数据容器),而不是真正的对象类,在编组和数据分解过程中,还可能限制应用数据的定制转换的灵活性。在本文后面,我会权衡代码生成和映射绑定这两种方法(请参阅映射绑定 vs. 代码生成)。 数据和代码 清单 1. 样本文档<?xml version="1.0"?> 图 1 显示了用于映射数据绑定到这些文档的类结构。为了进行比较,我将在有关各个数据绑定框架章节中显示生成的类结构。这里包含的这些图仅仅是所有情况的缩略图;如果要看全图,请单击这个小图像。 图 1. 映射绑定类图(单击进行放大) JAXB 的 EA 版本基于具有创新意义的拉解析器(pull parser)设计,这种设计使验证可以方便地构建到生成的数据分解代码中。它根据 DTD 生成代码,构建在解析 XML 文档时自动验证 XML 文档结构(而不是数据)的类。我们期望这种方法能快速和有效地处理 XML 和 Java 语言对象之间的转换,但 EA 代码仅仅是部分实现,显然在成为完整的实现之前,仍需要做大量工作。 专家组不久之后开始收到关于 EA 发行版的反馈。作为对反馈意见的部分响应中,他们研究决定重新架构 JAXB,之后更新了网站,声明 JAXB 在几个方面正在得到增强。该站点还声明,下一版本在 API 级上不与早期版本兼容 — 但您仍然可以下载 EA 版本。 重新架构 JAXB JAXB 项目的 SUN JSR 负责人 Joseph Fialli 把这么大的变化归结为以下一些因素。主要问题是扩展原有代码库以支持 W3C XML Schema 的复杂性。这是一个相当复杂的规范,以至于在批准之后的两年多时间里,在所有平台上,仍然只有少数几个解析器能接近完全符合规范。最初的 JAXB 代码需要实际对象来控制验证,而且将这种方法扩展到 Schema 将耗费太多精力,以至于在合理的期限内无法实现这项工作。 为适应 Schema 而做出变更的同时,专家组还决定重新考虑处理验证的方法。原来的 JAXB 代码无条件地验证文档的结构,如果发现错误,则抛出异常并中止处理。Fialli 说,在公众的意见中,抱怨这种方法局限性太大、限制太严 — 在一些情况下,用户希望能够一次检查多个验证错误,而在另一些情况下,则希望完全禁用验证(或者由于性能原因,或者在编组没有精确匹配文法的文档时)。新的 JAXB 体系结构能够满足这两种需求。 最后,专家组决定放弃单个绑定框架运行时(就象在原来 EA 发行版中所看的)的想法。而采用接口方法,其实质是可以使用不同的数据绑定框架。这使用户代码可以在各框架之间进行移植,而不需移植生成的类 — 这些类特定于专门的数据绑定框架,它们只能由该框架运行。强制性的 SAX 2.0 解析器支持替代了 EA 运行时中所使用的拉解析器方法,对于其它解析器(可能包括新的拉解析器,该解析器基于用于 XML 的流式 API,JSR 173 正在定义此 API),提供可选的特定于框架的支持,数据结构本身被更改为类 JavaBean 的数据对象,外部框架可以方便地操作此数据对象。 JAXB beta 测试版 图 2. JAXB 接口类图(单击进行放大) 用 JAXB 根据 Schema 描述生成代码非常简单。所提供的绑定编译器 xjc 是一个命令行工具。它将 Schema 文档作为输入,将文件生成到指定的输出包和目标目录。其中所具有的选项还使用户可以控制生成的代码文件是否是只读的,以及是否严格验证 Schema 描述。 通过使用绑定声明,JAXB 规范定义了一些方法来定制生成数据绑定的一些方面。包括: 用于控制所生成类的名称和属性的选项 总体说来,JAXB 正成为一种功能强大而灵活的工具,它用于将 Java 语言代码绑定到 W3C XML Schema 文法所定义的文档。由于有可能批准将 JAXB 作为一个 Java 平台标准,因此它将会受到广泛支持,而且在各实现之间移动绑定应用程序会象在 servlet 引擎之间移动 Web 应用程序一样容易(一般来讲,很简单,但偶尔也会有一些波折)。 然而,JAXB 确实也有一些缺点。目前最大的局限是只有用于评估用途的许可证。在该产品发行版(目前计划在这个季度发布)之前,JAXB 还无法用于实际项目中。另外,定制的程度也局限于只能应用到生成的代码。在许多情形中,您可以为 JAXB 所定义的接口定义自己的实现类,但这些接口本身总是与 Schema 描述联系在一起,不太可能进行修改。 Castor 图 4. Castor 生成的类图(单击进行放大) Castor 的当前 beta 测试版(我写这篇文章时,该版本为 0.9.4.1)不支持在代码生成中进行任何实质的定制,但这种情况有望得到改变。下一 beta 测试发行版预计将支持使用映射文件来控制代码生成的各个方面。起初,在这些方面中,只支持类名和包名,但从更长远来看,计划将添加对用户所提供的实现类的支持。Castor 开发人员还计划在 Castor 中支持 JAXB,可能是通过使用某类兼容性层来实现这一点。 用 Castor 根据 Schema 描述生成代码与用 JAXB 一样方便,使用的基本选项也一样。Castor 确实使用一些附加的命令行参数选项,而且通过属性文件设置,甚至提供了更多选项。这些选项主要用在一些特殊的情形中,但不包括象 JAXB 那样通过 Schema 文档注释提供对类名和验证的控制。 现在,用 Castor 来生成源代码这种方法的主要缺点是对定制的支持有限。这种情形正在开始发生转变,可以用 Castor 的映射数据绑定方法来实现实质的定制(见前一篇文章中的描述 — 请参阅参考资料),我期望最终在定制方面至少与源代码生成方法具有同样的灵活性。从长远来看,这将使它的适应性比 JAXB 更强。 Castor 按照 BSD 样式的许可证进行发布,完全可用于商业用途,而没有什么重大限制。它看起来相当稳定,但每当遇到需要修正错误时,您将需要更新到最新的开发代码(或等待新的 beta 测试发行版)。 JBind 图 5. JBind 生成的类图(单击进行放大) 实质上,JBind 采用与前面框架大不相同的方法来处理文档数据。JBind 不生成 JavaBean 样式的数据类(但 JAXB 和 Castor 是这样做的),而是将一切存储在文档模型(目前为 DOM 级别 2 实现)中,构建绑定代码做为前端(facade)来访问存储在文档模型中的数据。这是一种非常有趣的方法,如果完全实现,这可能具有一些不错的跨范例好处。目前这种方法所具有的唯一好处是在生成代码中支持基于 XPath 的约束和访问方法。由于存储机制相对于 JBind 的主旨是次要的,因此将来这种机制还可能会有所变动。 JBind 所具有的好处是,在考虑过的所有数据绑定框架中,它支持 Schema 最彻底,并且提供上面所说的 XPath 扩展。如果应用程序的核心是处理 XML 文档,则使用由 JBind 构造的“XML 代码”框架可能非常简单。对于一般的数据绑定用法,如果应用程序涉及到 XML 文档,而不是其重点时,则其它数据绑定方法可能会更简单些。由于数据分解时需要验证以及由于文档模型后端存储机制(我将在第 2 部分更详细地讲述此问题),因此与其它框架相比,JBind 还存在明显的性能劣势。JBind 是按照 Apache 样式的许可证分发的,完全可用于商业用途。 Quick 图 6. Quick 生成的类图(单击进行放大) QDML 文档提供文档描述,它大致相当于 DTD,不过添加了一些类型和继承。 再对这些文件进行一些手工编辑,则可以避免生成用于该对象类的新代码,直接链接到 Castor 映射绑定所使用的现有的类。这种可以使用现有类的能力是一项功能非常强大的特性。由于模式文件很复杂,而且为了利用该特性必须做大量的更改,这些因素稍微降低了 Quick 的实用性,但这确实展示了 Quick 的灵活性。 灵活性是 Quick 最强大的特性。使用 Quick 的主要缺点是各种模式文件的复杂性,以及缺乏对 Schema 文法的支持。另外,使用 Quick 时,获得帮助看来也很困难:在论坛和邮件列表中,提出的问题常常得不到任何响应。Quick 的许可证遵循 GNU 库(GNU Library)或次通用公共许可证(Lessor General Public License,LGPL),这种许可证允许自由项目和商业项目使用该软件。 Zeus 图 7. Zeus 生成的类图(单击进行放大) 不象前面所讨论过的其它任何框架,Zeus 只支持 String,而不支持其它类型的值,譬如 int 或 Date。它还缺乏对引用的支持,所以不能直接进行数据分解或编组图结构。这存在很大的局限性 — 由于数据绑定可以利用类型数据值和对象间链接的透明处理所提供的便利性,因此这给数据绑定带来许多实用性。没有这些特性的支持,Zeus 更象是一种经过裁减的文档模型,而不象是一个完整的数据绑定框架。 如果只使用 String 值,则考虑使用 Zeus 可能是不错的选择。使用 Zeus 的主要缺点是,提供的绑定形式有限,从整体上看,该项目进展缓慢。与使用 Quick 一样,您可能会发现难以找到问题的答案。Zeus 按照 Enhydra 公共许可证 V1.1 进行分发,该许可证来自 Mozilla 公共许可证。 映射绑定 vs. 代码生成 代码生成自动构建反映 XML 文档结构(换句话说,是 DTD 或 Schema 形式的文法)的类,这使您可以非常快速地开始使用文档。当代码生成基于 Schema 描述时,所构造的类可以包括完整的数据类型信息(尽管用此方法存在一些问题;许多 Schema 数据类型在 Java 语言中没有直接对应的数据类型)。用代码生成,您还可以将验证构建进所构造的类中,从而要么自动检查值(当设置好它们时),要么按照需要检查有效性。因此,您可以确保通过编组所生成的文档总是与所期望的结构相匹配。 代码生成方法的主要缺点是相对于其优点而言。通过如此贴实地反映文档结构,该方法使应用程序代码和文档结构之间紧密耦合。如果文档结构发生变化,再需要重新生成代码,并修改应用程序代码以使用最终修改后的数据类。 通常您还需要使用整个文档结构,为了生成代码,不易于对整个结构划分子集。如果正在使用带有许多可选组件的复杂结构(也许作为业界标准而定义的),而应用程序使用的文档只用这些组件中的某个子集,则这可能会有问题。对于这些框架中的大多数,使用它们时所生成的类将总是与整个文档结构匹配。您可能还需要在运行时包含所有这些生成的类,这取决于所使用的框架。对于应用程序,这导致代码过度膨胀以及数据模型过度复杂。当然,通过编辑 DTD 或者 Schema 以消除不需要的组件,您可以避免这种情况 — 但随之而来当基本文法发生任何变化时,都需要维护您的修改,这又带来一组新的问题。 映射绑定(譬如由 Castor 或 Quick 实现的映射绑定)比代码生成具有更大的灵活性。使用真正的对象类将数据和行为组合在一起。也可以在一定程度上解除对象类与实际 XML 之间的耦合。修改映射定义(而不需要改变应用程序代码)通常处理 XML 文档结构中微小的变化。甚至可以用一种格式定义单独的输入和输出映射来对文档进行数据分解,并用另一种格式编组它们。映射绑定的缺点是,在设置方面,它确实比生成代码方法需要花费更多精力。 总之,对于所有应用程序,没有一种方法总是最佳的。如果使用由 Schema 或 DTD 定义的稳定文档结构,并且该结构适合应用程序的需要,则代码生成方法可能是最佳方法。如果使用现有的 Java 语言类,或者希望使用类的结构,该结构反映应用程序对数据用法,而不是 XML 文档结构,则映射方法可能最佳。遗憾的是,当前大多数的开发工作主要集中在代码生成而不是映射。这种局限导致目前只有 Castor 和 Quick 才有这种映射方法。 结束语 一旦 JAXB 作为产品发行版使用(当前的 beta 测试版许可证仅允许用于评估),则它看起来将是一项非常吸引人的选择。目前 Castor 似乎比 JAXB 支持更多定制,但 JAXB 将提供可在各实现间进行移植的好处。JAXB 也很可能被用在其它 Java 平台标准(譬如用于 Web 服务的 JAX-RPC 标准)中,所以编写 JAXB 的应用程序在将来可能在插件上兼容这些标准。 JBind 提供了最佳的 Schema 支持。如果应用程序适合“XML 代码”模型,并且对性能的需求也不迫切,则 JBind 可能是很好的选择,但对于使用一般的 XML 数据绑定,它显得比较笨拙。Quick 提供了非常大的灵活性且功能强大,但它只支持 DTD 文法,而且使用起来相当复杂。Zeus 简单且容易,但它(与 Quick 一样)只支持 DTD,另外,只允许访问作为 String 值的数据。 最后三个框架似乎更适合具有特殊需求的应用程序,而非一般用途。如果文档只有 DTD 描述,而没有模式,则出于这个原因,您可能希望尝试 Quick 或 Zeus。对于大多数应用程序,这不是主要关心的问题,因为有许多可用于将 DTD 转换到模式的应用程序(尽管可能需要一些手工调整)。在 Castor 分发版中包括了一个这样的程序(正如在 Castor XML FAQ 中所提到的,org.exolab.castor.xml.dtd.Converter)。 在第 2 部分中,我将展示这些数据绑定框架的性能结果,这些性能是在一些样本文档上使用这些框架测试出的。这些结果涉及了生成代码方法和映射绑定方法,为了进行比较,包含了文档模型。我确实惊讶地看到……,但等等,现在我不能把一切都告诉您。另外提醒您,在下个星期别错过这个完全关于性能的“故事” — 我保证您会找到值得一读的结果! 参考资料 请参与本文的论坛。(您也可以单击本文顶部或底部的讨论来访问该论坛)。 关于作者 |
W 3 C h i n a ( since 2003 ) 旗 下 站 点 苏ICP备05006046号《全国人大常委会关于维护互联网安全的决定》《计算机信息网络国际联网安全保护管理办法》 |
70.313ms |