技术开发 频道

Ajax 的 Java 对象序列化



XML 绑定框架

近些年来,已经开发了多个 Java API 来简化 XML 文档到 Java 对象图的绑定过程。多数都提供了 XML 编排和拆解;也就是说,它们可以在 Java 对象图和 XML 之间执行双向会话。这些框架封装了 XML 处理的全部工作,这意味着应用程序代码只需要处理普通的 Java 类。它们还希望提供有用的辅助功能,例如文档验证。笼统来说,这些框架采用了两种不同的方式:代码生成和对象到 XML 映射。我将分别解释这两种方式。

代码生成方式

使用代码生成的框架包括 XMLBeans、JAXB、Zeus 和 JBind。Castor 也能使用这项技术。这类框架的起点是描述文档数据类型的 XML 方案。使用框架提供的工具,就可以生成代表这些方案定义类型的 Java 类。最后,用这些生成的类编写应用程序,表示自己的模型数据,并通过框架提供的一些辅助机制把数据序列化成 XML。

如果应用程序要使用大型 XML 语法,那么代码生成方式是个很好的方法。在数十个类上编写定制 XML 序列化代码的可伸缩性问题由此消除。另一方面,也不再需要定义自己的 JavaBean。框架生成的 Java 类通常非常符合 XML 的结构,所以对它们进行编码很难。而且,生成的类变成哑数据容器,因为一般不能向它们添加行为。一般来说,在应用程序代码中要做些妥协,才能很好地处理方案生成的类型。另一个缺陷是如果修改方案,会造成生成的类也要修改,所以也就会对围绕它们编写的代码带来相应的影响。

这种类型的 XML 绑定框架在数据拆解时最有用(例如,使用 XML 文档并把它们转化成 Java 对象)。除非拥有大型数据模型而且有可能从生成的类中获益,否则基于代码生成的框架对于 Ajax 应用程序来说可能有很大的杀伤力。

映射方式

采用映射方式的框架包括 Castor 和 Apache Commons Betwixt。映射通常是比代码生成更灵活和更轻量的解决方案。首先,可以像通常一样编写 JavaBean,包括任何行为以及任何自己喜欢的方便的方法。然后,在运行时,调用框架中基于内省的编排器,并根据对象成员的类型、名称和值生成 XML 文档。通过定义类的映射文件,可以覆盖默认的绑定策略,并就类在 XML 中的表示方式对编排器提出建议。

这种方法是在可伸缩性与灵活性之间的良好折中。可以按照自己喜欢的方式编写 Java 类,编排器负责处理 XML。虽然映射定义文件编写起来简单,可伸缩性也足够好,但是映射规则最多只能改变标准的绑定行为,而且在对象结构和它们的 XML 表示之间总要残留一些耦合。最终,可能不得不在 Java 表示或 XML 格式之间任选一个做些折中,才能让映射方法起作用。

数据绑定总结

Dennis Sosnoski 就 XML 数据绑定 API 的主题,在代码生成和代码映射两个方面写了深入的文章。如果想进一步研究这个领域,我推荐他在 Castor 和代码生成框架方面的精彩文章(请参阅 参考资料 中的链接)。

总之,代码生成方式损失了过多的灵活性和方便性,对于典型的 Ajax 应用程序用处不大。另一方面,基于映射的框架可能工作得很好,但是要恰到好处地调整它们的映射策略,以便从对象生成需要的 XML。

所有的 XML 绑定 API 都具有手工序列化技术的一个主要不足:模型和视图的耦合。被限制为一个类型一个 XML 表示,就意味着在网络上总要有冗余数据传输。更严重的问题是,在情况要求客户端代码使用专门视图时,客户端代码却无法得到它,所以可能要费力地处理给定对象图的一成不变的视图。

在传统的 Web 应用程序开发中,采用页面模板系统把视图生成与控制器逻辑和模型数据干净地分离。这种方法在 Ajax 场景中也会有帮助。

页面模板系统

任何通用目的的页面模板技术都可以用来生成 XML,从而使 Ajax 应用程序根据自己的数据模型生成任何 XML 响应文档。额外收获是:模板可以用简单的、表现力强的标记语言编写,而不是用一行行的 Java 代码编写。清单 5 是一个 JSP 页面,采用了 Customer bean 并表示出定制的 XML 视图,适合客户端代码生成订单历史组件。


清单 4. 生成订单历史文档的 JSP


            <?xml version="1.0"?>
            <%@ page contentType="application/xml" %>
            <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
            <c:set var="cust" value="${requestScope.customer}"/>
            <orderhistory username="${cust.username}">
            <c:forEach var="order" items="${cust.orders}">
            <order id="${order.id}" cost="${order.formattedCost}">
            <date>${order.date}</date>
            <items>
            <c:forEach var="item" items="${order.items}">
            <item id="${item.id}">
            <name><c:out value="${item.name}" escapeXml="true"/></name>
            <price>${item.formattedPrice}</price>
            </item>
            </c:forEach>
            </items>
            </order>
            </c:forEach>
            </orderhistory>
            

这个简洁的模板只输出订单历史视图需要的数据,不输出不相关的资料(例如商品说明)。创建产品搜索视图的定制 XML 应当同样简单,这个视图包含每个商品的完整说明和库存水平。

模板的问题

另一方面,现在我需要为每个不同视图创建一个新 JSP,而不能仅仅把需要的对象图组织起来并序列化它。从设计的角度来说,许多人可能会有争议,认为这无论如何是件好事,因为这意味着正式地考虑服务器要生成的文档类型。而且,因为我现在要处理通用的模板环境,而不是特定于 XML 的 API,所以确保标记匹配、元素和属性的顺序正确以及 XML 实体(例如 <&)正确转义就成了我的责任。JSP 的核心 out 标记使后面这项工作变得很容易,但是不是所有的模板技术都提供了这样的机制。最后,没有方便的途径可以在服务器端根据方案检验生成的 XML 文档的正确性,但这毕竟不是要在生产环境中做的事,可以方便地在开发期间处理它。

0
相关文章