面向Java程序员的_第1页
面向Java程序员的_第2页
面向Java程序员的_第3页
面向Java程序员的_第4页
面向Java程序员的_第5页
已阅读5页,还剩15页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、面向 Java开发人员的Ajax:构建动态的Java应用程序Ajax为更好的Web应用程序铺平了道路级别:中级打印本页将此页作为电子邮件发送讨论样例代码Philip McCarthy (),软件开发顾问,独立咨询顾问2005年10月20日在Web应用程序开发中,页面重载循环是最大的一个使 用障碍,对于Java?开发人员来说也是一个严峻的挑 战。在这个系列中,作者 Philip McCarthy介绍了一种 创建动态应用程序体验的开创性方式。Ajax (异步JavaScript 和XML)是一种编程技术,它允许为基于Java的Web应用程序把 Java技术、XML和JavaScript 组合起来,

2、从而打破页面重载的范式。Ajax (即异步JavaScript和XML)是一种 Web应用程序开发的手段,它采用客户端脚本与 Web服务器交换数据。所以,不必采用会中断交互的完整页面刷 新,就可以动态地更新 Web页面。使用Ajax,可以创建更加丰富、更加动态的 Web应用程序用户界面,其即时性与可用性甚至能够接近本机桌面应用程序。Ajax不是一项技术,而更像是一个模式 一一一种识别和描述有用的设计技术的方式。Ajax是新颖的,因为许多开发人员才刚刚开始知道它,但是所有实 现Ajax应用程序的组件都已经存在若干年了。它目前受到重视是因为在2004和2005年出现了一些基于Ajax技术的非常棒的

3、动态 Web UI,最著名的就是 Google的GMail和Maps应用程序,以及照片共享站点 Flickr 。这些用户界 面具有足够的开创性,有些开发人员称之为“Web,因此对Ajax应用程序的兴趣飞速上升。在这个系列中,我将提供使用 Ajax开发应用程序需要的全部工具 。在第一篇 文章中,我将解释Ajax背后的概念,演示为基于Java的Web应用程序创建 Ajax界面的基本步骤。我将使用代码示例演示让 Ajax应用程序如此动态的服 务器端Java代码和客户端JavaScript。最后,我将指出Ajax方式的一些不 足,以及在创建Ajax应用程序时应当考虑的一些更广的可用性和访问性问题。更好

4、的购物车可以用Ajax增强传统的Web应用程序,通过消除页面装入从而简化交互。为 了演示这一点,我采用一个简单的购物车示例,在向里面添加项目时,它会动态 更新。这项技术如果整合到在线商店,那么用户可以持续地浏览和向购物车中添 加项目,而不必在每次点击之后都等候完整的页面更新。虽然这篇文章中的有些代码特定于购物车示例,但是演示的技术可以应用于任何 Ajax应用程序。清单 1显示了购物车示例使用的有关 HTML代码,整篇文章中都会使用这个 HTML。清单1.购物车示例的有关片断Name Description Price Hat Stylish bowler hat $Add to CartTot

5、al cost: $回页首Ajax往返过程Ajax交互开始于叫作 XMLHttpRequest的JavaScript 对象。顾名思义,它 允许客户端脚本执行HTTP请求,并解析XML服务器响应。Ajax往返过程的第 一步是创建 XMLHttpRequest的实例。在 XMLHttpRequest对象上设置请求 使用的HTTP方法(GET或 POST以及目标URL。现在,您还记得 Ajax的第一个 a 是代表 异步(asynchronous)吗在发送HTTP请求时,不想让浏览器挂着等候服务器响应。 相反,您想让浏览器继续 对用户与页面的交互进行响应,并在服务器响应到达时再进行处理。为了实现这 个

6、要求,可以在 XMLHttpRequest上注册一个回调函数,然后异步地分 派XMLHttpRequest。然后控制就会返回浏览器,当服务器响应到达时,会调用 回调函数。在Java Web服务器上,请求同其他 HttpServletRequest 样到达。在解析 了请求参数之后,servlet调用必要的应用程序逻辑,把响应序列化成XML,并 把 XML 写入 HttpServletResponse。回到客户端时,现在调用注册在 XMLHttpRequest上的回调函数,处理服务器 返回的XML文档。最后,根据服务器返回的数据,用 JavaScript 操纵页面的 HTML DOM把用户界面更新

7、。图1是Ajax往返过程的顺序图。图1. Ajax往返过程现在您对Ajax往返过程有了一个高层面的认识。下面我将放大其中的每一步由于Ajax 方骤,进行更详细的观察。如果过程中迷了路,请回头看图 1 式的异步性质,所以顺序并非十分简单。回页首分派 XMLHttpRequest我将从Ajax序列的起点开始:创建和分派来自浏览器的XMLHttpRequest。不幸的是,不同的浏览器创建XMLHttpRequest的方法各不相同。清单2的JavaScript函数消除了这些依赖于浏览器的技巧,它可以检测当前浏览器要使 用的正确方式,并返回一个可以使用的XMLHttpRequest。最好是把它当作辅助代

8、码:只要把它拷贝到JavaScript 库,并在需要 XMLHttpRequest的时候使 用它就可以了。清单2.创建跨浏览器的XMLHttpRequest/* Returns a new XMLHttpRequest object, or false if this browser* doesnt support it*/function newXMLHttpRequest() var xmlreq = false;if 分派 Add to Cart XMLHttpRequest/* Adds an item, identified by its product code, to the s

9、hopping cart* itemCode - product code of the item to add.*/function addToCart(itemCode) (POST, true);(action=add&i tem=+itemCode);这就是建立Ajax往返过程的第一部分,即创建和分派来自客户机的HTTP请求。接下来是用来处理请求的 Java servlet 代码。回页首servlet 请求处理用servlet 处理 XMLHttpRequest,与处理普通的浏览器 HTTP请求一样。可 以用()得到在POST请求体中发送的表单编码数据。Ajax请求被放进与来 自应用程

10、序的常规 Web请求一样的 HttpSession中。对于示例购物车场景来说,这很有用,因为这让我可以把购物车状态封装在 JavaBean中,并在请求之 间在会话中维持这个状态。清单4是处理Ajax请求、更新购物车的简单servlet 的一部分。Cart bean 是从用户会话中获得的,并根据请求参数更新它的状态。然后 Cart被序列化 成XML,XML又被写入ServletResponse。重要的是把响应的内容类型设置为application/xml,否则 XMLHttpRequest不会把响应内容解析成 XMLDOM清单4.处理Ajax请求的servlet 代码public void do

11、Post(HttpServletRequest req, HttpServletResponse res)throws Cart cart = getCartFromSession(req);String action = (action);String item = (item);if (action != null)&(item != null) quals(action) (item); else if (remove.equals(action) (item);(application/xml);().write(cartXml);清单5显示了 ()方法生成的示例XML。它很简单。请注

12、意 cart 元素的gen erated属性,它是 () 生成的一个时间戳。清单5. Cart 对象的XML序列化示例Hat2Chair1Dog 1如果查看应用程序源代码(可以从 下载 一节得到)中的,可以看到生成XML 的方式只是把字符串添加在一起。虽然对这个示例来说足够了,但是对于从Java 代码生成XML来说则是最差的方式。我将在这个系列的下一期中介绍一些更好 的方式。现在您已经知道了CartServlet 响应 XMLHttpRequest的方式。下一件事就是返回客户端,查看如何用 XML响应更新页面状态。回页首用JavaScript进行响应处理XMLHttpRequest的ready

13、State属性是一个数值,它指出请求生命周期的状态。它从0 (代表“未初始化”)变化到4 (代表“完成”)。每 次 readyState变化时,readystatechange事件就触发,由on readystatecha nge属性指定的事件处理函数就被调用。在清单3 中已经看到了如何调用getReadyStateHa ndler()函数创建事件处理函数。然后把这个事件处理函数分配给on readystatecha nge 属性。getReadyStateHa ndler()利用了这样一个事实:函数是JavaScript中的一级对象。这意味着函数可以是其他函数的参数,也可以创建和返回其他函数

14、。getReadyStateHandler()的工作是返回一个函数,检查 XMLHttpRequest 是否已经完成,并把XML响应传递给调用者指定的事件处理函数。清单6是 getReadyStateHa ndler()的代码。清单 6. getReadyStateHa ndler()函数/* Returns a function that waits for the specified XMLHttpRequest* to complete, then passes its XML response to the given handler function.* req - The XMLH

15、ttpRequest whose state is changing* responseXmlHandler - Function to pass the XML response to*/function getReadyStateHandler(req, responseXmlHandler) 更新页面,反映购物车的XML文档function updateCart(cartXML) var quantity = (quantity)。 JnnerHTML =(total);到此,整个Ajax往返过程完成了,但是您可能想让 Web应用程序运行一下查 看实际效果(请参阅 下载 一节)。这个示例

16、非常简单,有很多需要改进之处。 例如,我包含了从购物车中清除项目的服务器端代码,但是无法从 UI访问它 作为一个好的练习,请试着在应用程序现有的JavaScript 代码之上构建出能够 实现这个功能的代码。回页首使用Ajax的挑战就像任何技术一样,使用Ajax也有许多出错的可能性。我目前在这里讨论的问 题还缺乏容易的解决方案,但是会随着Ajax的成熟而改进。随着开发人员社区 增加开发Ajax应用程序的经验,将会记录下最佳实践和指南。XMLHttpRequest 的可用性Ajax开发人员面临的一个最大问题是:在没有 XMLHttpRequest可用时该如 何响应虽然主要的现代浏览器都支持XMLH

17、ttpRequest,但仍然有少数用户的浏览器不支持,或者浏览器的安全设置阻止使用 XMLHttpRequest。如果开发的Web 应用程序要部署在企业内部网,那么可能拥有指定支持哪种浏览器的权力,从而可以认为 XMLHttpRequest总能使用。但是,如果要部署在公共 Web上,那 么就必须当心,如果假设 XMLHttpRequest可用,那么就可能会阻止那些使用 旧的浏览器、残疾人专用浏览器和手持设备上的轻量级浏览器的用户使用您的应 用程序。所以,您应当努力让应用程序“平稳降级”,在没有 XMLHttpRequest支持的浏览器中也能够工作。在购物车的示例中,把应用程序降级的最好方式可能

18、是让 Add to Cart按钮执行一个常规的表单提交,刷新页面来反映购物车更新后的状 态。Ajax的行为应当在页面装入的时候就通过 JavaScript 添加到页面,只有 在XMLHttpRequest可用时才把JavaScript 事件处理函数附加到每个Add to Cart 按钮。另一种方式是在用户登录时检测XMLHttpRequest是否可用,然后相应地提供应用程序的 Ajax版本或基于表单的普通版本。可用性考虑关于Ajax应用程序的某些可用性问题比较普遍。例如,让用户知道他们的输入已经注册了可能是重要的,因为沙漏光标和spinning 浏览器的常用反馈机制“throbber ”对 X

19、MLHttpRequest 不适用。一种技术是用“ Nowupdating. ”类型的信息替换Submit按钮,这样用户在等候响应期间就不会反复单击按钮了。另一个问题是,用户可能没有注意到他们正在查看的页面的某一部分已经更新 了。可以使用不同的可视技术,把用户的眼球带到页面的更新区域, 从而缓解这 个问题。由Ajax更新页面造成的其他问题还包括:“破坏了”浏览器的后退按 钮,地址栏中的URL也无法反映页面的整个状态,妨碍了设置书签。请参阅 参 考资料一节,获得专门解决Ajax应用程序可用性问题的文章。服务器负载用Ajax实现代替普通的基于表单的UI,会大大提高对服务器发出的请求数量。 例如,一

20、个普通的Google Web搜索对服务器只有一个请求,是在用户提交搜索 表单时出现的。而Google Suggest试图自动完成搜索术语,它要在用户输入时 向服务器发送多个请求。在开发Ajax应用程序时,要注意将要发送给服务器的 请求数量以及由此造成的服务器负荷。 降低服务器负载的办法是,在客户机上对 请求进行缓冲并且缓存服务器响应(如果可能的话)。还应该尝试将Ajax Web应 用程序设计为在客户机上执行尽可能多的逻辑,而不必联络服务器。处理异步非常重要的是,要理解无法保证 XMLHttpRequest会按照分派它们的顺序完 成。实际上,应当假设它们不会按顺序完成,并且在设计应用程序时把这一

21、点记 在心上。在购物车的示例中,使用最后更新的时间戳来确保新的购物车数据不会 被旧的数据覆盖(请参阅 清单7)0这个非常基本的方式可以用于购物车场景, 但是可能不适合其他场景。所以在设计时请考虑如何处理异步的服务器响应。回页首结束语现在您对Ajax的基本原则应当有了很好的理解,对参与Ajax交互的客户端和 服务器端组件也应当有了初步的知识。这些是基于Java的Ajax Web应用程序 的构造块。另外,您应当理解了伴随Ajax方式的一些高级设计问题。创建成功 的Ajax应用程序要求整体考虑,从UI设计到JavaScript 设计,再到服务器 端架构;但是您现在应当已经武装了考虑其他这些方面所需要

22、的核心Ajax知识。如果使用这里演示的技术编写大型 Ajax应用程序的复杂性让您觉得恐慌,那么 有好消息给您。由于Struts、Spring和Hibernate 这类框架的发展把 Web应 用程序开发从底层Servlet API 和JDBC的细节中抽象出来,所以正在出现简 化Ajax开发的工具包。其中有些只侧重于客户端,提供了向页面添加可视效果 的简便方式,或者简化了对 XMLHttpRequest的使用。有些则走得更远,提供 了从服务器端代码自动生成 Ajax接口的方式。这些框架替您完成了繁重的任 务,所以您可以采用更高级的方式进行 Ajax开发。我在这个系列中将研究其中 的一些。Ajax社

23、区正在快速前进,所以会有大量有价值的信息涌现。在阅读这个系列的 下一期之前,我建议您参考 参考资料 一节中列出的文章,特别是如果您是刚 接触Ajax或客户端开发的话。您还应当花些时间研究示例源代码并考虑一些增强它的方式。在这个系列的下一篇文章中,我将深入讨论XMLHttpRequest API,并推荐一些从JavaBean方便地创建XML的方式。我还将介绍替代XML进行Ajax数据 传递的方式,例如 JSON (JavaScript Object Notation )轻量级数据交换格式。回页首下载描述名字大小下载方法Sample code8 KBHTTP关于下载方法的信息参考资料学习您可以参阅

24、本文在developerWorks全球站点上的英文原文。“ Beyond the DOM( Dethe Elza, developerWorks ,2005 年 5 月): 进行XML文档访问的有用的JavaScript 技术。“ AJAX及使用E4X编写Web服务脚本,第1部分” (Paul Frema ntle 和 Anthony Elder,developerWorks,2005 年 4 月):用 Ajax 在支持 E4X JavaScript扩展的浏览器中进行 SOAP调用。“Ajax: A NewApproach to WebApplications ”( Jesse JamesGa

25、rrett , Adaptive Path ,2005年2月):介绍 Ajax 起源的短文。The Java BluePrints Solutions Catalog :介绍了 Ajax 在几个常见 Web 应用程序场景中的应用。:包含多项改进Ajax应用程序的UI技术。XMLHttpRequest Usability Guidelines:对使用 Ajax 提高用户体验的建议。Ajax Mistakes : Ajax应用程序应当避免的可用性问题。Java技术专区:在这里可以找到关于Java编程的各个方面的文章获得产品和技术Mozilla Firefox : DOMnspector 和 Jav

26、aScript Debugger 扩展消除了 许多Ajax开发的痛苦。讨论参与论坛讨论。developerWorks blogs :加入 developerWorks 社区。面向Java开发人员的Ajax:Ajax的Java对象序列化在Ajax应用程序中序列化数据的五种途径级别:中级Philip McCarthy (),软件开发顾问,独立顾问2005年10月24日如果您正在使用异步 JavaScript 和XML( Ajax )进行Java ? Web开发,那么 您最关心的问题可能就是把数据从服务器传递给客户机。在 面向Java开发人员的Ajax 系列的第二篇文章中,Philip McCart

27、hy 介绍了 Java对象序列化 的五种方式,并提供了选择最适合应用程序的数据格式和技术所需要的全部信 息。在这个系列的第一篇文章 中,我介绍了 Ajax的构造块:如何用JavaScript XMLHttpRequest对象从Web页面向服务器发送 异步请求。如何用Java servlet处理和响应请求(向客户机返回 XML文档)。如何在客户端用响应文档更新页面视图。这一次,我将继续讨论 Ajax开发的基础知识,但是将侧重于许多 Java Web开 发人员最关心的问题:为客户机生成数据。多数Java开发人员已经把模型-视图-控制器(MVC模式应用在他们的 Web应 用程序上。在传统的Web应用

28、程序中,视图组件由JSP或者其他表示技术(例 如Velocity 模板)构成。这些表示组件动态地生成全新的 HTML页面,替代用 户以前正在查看的页面,从而更新用户界面。但是,在Java Web应用程序使用Ajax UI的情况下,基于从 XMLHttpRequest的响应接收到的数据, JavaScript客户端代码对于更新用户看到的内容负有最终责任。从服务器的角 度来看,视图成为它响应客户机请求而发送的数据表示。这篇文章侧重于可以用来生成 Java对象以数据为中心的视图的技术。我将演示 可以把JavaBeans变成XML文档的各种方法,并且讨论每种方法的优劣。您将 看到为什么XML并不总是最

29、好的途径:对于简单的 Ajax请求来说,传输纯文 本更好。最后,我将介绍 JavaScript 对象标注(JSON 。 JSON允许数据以序 列化的JavaScript 对象图的形式传输,在客户端代码中处理序列化的 JavaScript 对象图极为容易。关于示例我将使用一个示例应用程序和几个用例来演示这里讨论的技术特性和技术。图1显示的极为简单的数据模型可以表示示例用例。 这个模型代表在线商店中的顾客 帐户。顾客拥有以前订单的集合,每个订单包含几个商品。图1.简单的对象模型虽然 XMLHttpRequest对于发送数据使用的格式没有做任何限制, 但是对于多 数目的来说,只发送传统的表单数据是适

30、合的,所以我的讨论集中在服务器的响 应上。响应也可以有基于文本的格式,但是正如它的名字表示的,XMLHttpRequest具有内置的处理 XML响应数据的能力。这使 XML成为Ajax 响应的默认选择,所以我们从 XML格式开始讨论。从Java类产生XML把Ajax响应作为XML来传递有许多原因:每个支持Ajax的浏览器都有导航 XML文档的方法,也有许多服务器端技术可以处理XML数据。通过制定一个方案,描述要交换的文档类型,在 Ajax客户端和服务器端之间很容易定义合约, 而且如果服务器端架构采用面向服务的方式, 那么使用XML也可以允许非Ajax 客户机使用您提供的数据。我将考虑从Java

31、对象产生XML数据的三种方法,并讨论每种方法的优劣。自行进行序列化首先,可以从对象图以编程的方式生成 XML这种方式可以简单到只是在每个 JavaBean类中实现 toXml() 方法即可。然后就可以选择合适的 XMLAPI,让 每个bean提供表示自己状态的元素,并递归地对自己的成员调用对象图。显然, 这种方式无法扩展到大量的类,因为每个类都需要专门编写自己的XML生成代码。从好的方面来看,这是一个实现起来简单的方式,没有额外的配置支出或者 更复杂的构建过程支出,任何 JavaBean图都可以只用几个调用就变成 XML文 档。在本系列 前一篇文章 的示例代码中,我把XML标记字符串连接在一起

32、,实 现了 toXml()方法。上次我就提到过,这是个糟糕的方法,因为它把确保标记配对、实体编码等工作的负担放在每个toXml() 方法的代码中。在Java平台上有几个XML API可以替您做这些工作,这样您就可以把精力集中在 XML的 内容上。清单1用JDOM API实现了在线商店示例中表示订单的类中的 toXml()(请参阅图1 )。清单1. Order 类的toXml() 的JDOM实现public Element toXml() Element elOrder = new Element(order);(id,id);(cost,getFormattedCost();Element e

33、lDate = new Element(date).addContent(date);(elDate);Element elltems = new Element(items);for (lterator iter =();();)().toXml();(elItems);return elOrder;在这里可以看到用JDOM创建元素、使用属性和添加元素内容有多么简单。递归 地调用复合JavaBean的toXml()方法是为了取得它们子图的 Element表示。例如,items 元素的内容是通过调用 Order聚合的每 个 Item对象上的toXml()得到的。一旦所有的JavaBean都实现

34、了 toXml() 方法,那么把任意对象图序列化成 XML文档并返回给Ajax客户机就简单了,如清单2所示。清单2.从JDOM元素生成XML响应public void doGet(HttpServletRequest req, HttpServletResponse res)throws ServletException String custId = (username);Customer customer = getCustomer(custId);Element responseElem =();Document responseDoc = new Document(responseEl

35、em);(application/xml);new XMLOutputter().output(responseDoc,();JDOM再次把工作变得非常简单。只需要在对象图返回的XML元素外面包装一个 Documen,然后用 XMLOutputter 把文档写入servlet 响应即可。清单3 显示了用这种方式生成的 XML示例,用JDOM () 对 XMLOutputter 进行初 始化,格式化得非常好。在这个示例中,顾客只做了一个订单,包含两个商品。清单3.代表顾客的XML文档 James Hyrax08-26-2005Oolong 512MB CF Card 512 Megabyte T

36、ype 1 CompactFlash card. Manufactured by Oolong Industries $Fujak Superpix72 Camera Megapixel digital camera featuring six shooting modes and 3x optical zoom. Silver. $自行序列化的不足有趣的是,清单3中的代码展示了让JavaBean把自己序列化为XML的一个主 要不足。假设要用这个文档表示顾客的订单历史视图。 在这种情况下,不太可能 要显示每个历史订单中每个商品的完整说明,或者告诉顾客他或她自己的姓名。但是如果应用程序有一个Pr

37、oductSearch 类,它就是以Item bean列表的形式返回搜索结果,那么在Item 的XML表示中包含说明可能会有帮助。而且,Item 类上代表当前库存水平的额外字段, 在产品搜索视图中可能就是需要 显示的有用信息。但是,不管当前的库存水平是否与当前情况相关 (比如对顾客 的订单历史来说),这个字段都会从包含Item 的任何对象图中序列化出来。从设计的角度来看,这是数据模型与视图生成耦合的经典问题。 每个bean只能 用一种途径序列化自己,一成不变的方式意味着Ajax交互最终要交换它们不需 要交换的数据,因此造成客户端代码要从文档中找到需要的信息更加困难,而且也会增加带宽消耗和客户端

38、的 XML解析时间。这种耦合的另一个后果就是 XML 的语法不能脱离Java类独立变化。例如,对顾客文档的方案做修改,可能会影 响多个Java类,造成它们也不得不做修改和重新编译。我稍后会解决这些问题,但是首先来看一个对自行序列化方式的可伸缩性问题的 解决方案:XML绑定框架。XML绑定框架近些年来,已经开发了多个 Java API来简化XML文档到Java对象图的绑定 过程。多数都提供了 XML编排和拆解;也就是说,它们可以在 Java对象图和 XML之间执行双向会话。这些框架封装了 XML处理的全部工作,这意味着应用 程序代码只需要处理普通的Java类。它们还希望提供有用的辅助功能,例如文

39、 档验证。笼统来说,这些框架采用了两种不同的方式:代码生成和对象到XML映 射。我将分别解释这两种方式。代码生成方式使用代码生成的框架包括 XMLBeans JAXB Zeus和JBind 。 Castor也能使用 这项技术。这类框架的起点是描述文档数据类型的XML方案。使用框架提供的工具,就可以生成代表这些方案定义类型的 Java类。最后,用这些生成的类编 写应用程序,表示自己的模型数据,并通过框架提供的一些辅助机制把数据序列 化成XMLo如果应用程序要使用大型XML语法,那么代码生成方式是个很好的方法。在数 十个类上编写定制XML序列化代码的可伸缩性问题由此消除。另一方面,也不 再需要定义

40、自己的JavaBean。框架生成的Java类通常非常符合XML的结构, 所以对它们进行编码很难。而且,生成的类变成哑数据容器,因为一般不能向它 们添加行为。一般来说,在应用程序代码中要做些妥协, 才能很好地处理方案生 成的类型。另一个缺陷是如果修改方案,会造成生成的类也要修改,所以也就会 对围绕它们编写的代码带来相应的影响。这种类型的XML绑定框架在数据拆解时最有用(例如,使用XML文档并把它们 转化成Java对象)。除非拥有大型数据模型而且有可能从生成的类中获益, 否 则基于代码生成的框架对于Ajax应用程序来说可能有很大的杀伤力。映射方式采用映射方式的框架包括 Castor和Apache

41、Commo ns Betwixt。映射通常是比 代码生成更灵活和更轻量的解决方案。首先,可以像通常一样编写 JavaBean, 包括任何行为以及任何自己喜欢的方便的方法。 然后,在运行时,调用框架中基 于内省的编排器,并根据对象成员的类型、名称和值生成 XML文档。通过定义 类的映射文件,可以覆盖默认的绑定策略,并就类在 XML中的表示方式对编排 器提出建议。这种方法是在可伸缩性与灵活性之间的良好折中。可以按照自己喜欢的方式编写Java类,编排器负责处理XMLo虽然映射定义文件编写起来简单,可伸缩性也 足够好,但是映射规则最多只能改变标准的绑定行为,而且在对象结构和它们的XML表示之间总要残留

42、一些耦合。最终,可能不得不在 Java表示或XML格式 之间任选一个做些折中,才能让映射方法起作用。数据绑定总结Denn is Sos no ski就XML数据绑定API的主题,在代码生成和代码映射两个方 面写了深入的文章。如果想进一步研究这个领域,我推荐他在Castor和代码生 成框架方面的精彩文章(请参阅参考资料中的链接)。总之,代码生成方式损失了过多的灵活性和方便性, 对于典型的Ajax应用程序 用处不大。另一方面,基于映射的框架可能工作得很好,但是要恰到好处地调整 它们的映射策略,以便从对象生成需要的 XMLo所有的XML绑定API都具有手工序列化技术的一个主要不足: 模型和视图的耦

43、合。被限制为一个类型一个XML表示,就意味着在网络上总要有冗余数据传输。 更严重的问题是,在情况要求客户端代码使用专门视图时,客户端代码却无法得到它,所以可能要费力地处理给定对象图的一成不变的视图。在传统的Web应用程序开发中,采用页面模板系统把视图生成与控制器逻辑和 模型数据干净地分离。这种方法在 Ajax场景中也会有帮助。页面模板系统任何通用目的的页面模板技术都可以用来生成 XML,从而使Ajax应用程序根据 自己的数据模型生成任何 XML响应文档。额外收获是:模板可以用简单的、表 现力强的标记语言编写,而不是用一行行的Java代码编写。清单5是一个JSP 页面,采用了 Customer

44、bean并表示出定制的XML视图,适合客户端代码生 成订单历史组件。清单4.生成订单历史文档的JSP$这个简洁的模板只输出订单历史视图需要的数据,不输出不相关的资料(例如商品说明)。创建产品搜索视图的定制 XML应当同样简单,这个视图包含每个商 品的完整说明和库存水平。模板的问题另一方面,现在我需要为每个不同视图创建一个新 JSP,而不能仅仅把需要的对 象图组织起来并序列化它。从设计的角度来说,许多人可能会有争议,认为这无 论如何是件好事,因为这意味着正式地考虑服务器要生成的文档类型。而且,因为我现在要处理通用的模板环境,而不是特定于 XML的API,所以确保标记匹 配、元素和属性的顺序正确以

45、及 XML实体(例如 或 &)正确转义就成了 我的责任。JSP的核心 out标记使后面这项工作变得很容易,但是不是所有 的模板技术都提供了这样的机制。 最后,没有方便的途径可以在服务器端根据方 案检验生成的XML文档的正确性,但这毕竟不是要在生产环境中做的事,可以 方便地在开发期间处理它。不用XML的响应数据迄今为止,我介绍的所有技术都用XML文档的形式生成服务器响应。但是,XML 有一些问题。其中一个就是延迟。浏览器不能立即解析XML文档并生成DOM模 型,所以这会降低某些Ajax组件需要的“迅捷”感,特别是在较慢的机器上解 析大型文档的时候更是如此。“现场搜索”就是一个示例,在这种搜索中,

46、当用 户输入搜索术语时,就会从服务器提取搜索结果并显示给用户。 对于现场搜索组 件来说,迅速地响应输入是非常重要的,但是同时它还需要迅速而持续地解析服 务器的响应。延迟是一个重要的考虑因素,但是避免使用XML的最大原因是差劲的客户端DOMXPI。清单5显示了使用跨浏览器兼容的方式通过 DOM得到某个值的时候, 通常不得不面对的困难。清单5.在JavaScript 中导航XML响应文档用正则表达式处理XMLHttpRequest的responseText 对象var orderHistoryText =;var matches = (/(.*)/);var date = matches1;在某些

47、情况下,采用即时方式使用 responseText 会比较方便。但是,理想情 况下,应当有种途径,可以用一种能够让JavaScript 轻松导航、却没有XML处 理支出的格式表示复杂的结构化数据。幸运的是,确实存在这样一种格式。JavaScript对象标注实际上,JavaScript对象的大部分都由联合数组、数字索引数组、字符串、数 字或者这些类型的嵌套组合而成。因为所有类型都可以用JavaScript 直接声明,所以可以在一条语句中静态地定义对象图。清单7使用JSON语法声明了一个对象,并演示了如何访问这个对象。大括号表示联合数组(即对象),它的 键-值组合由逗号分隔。方括号表示数字索引数组

48、。清单7.用JSON在JavaScript中直接声明一个简单对象var band = name: The Beatles,members:name: John,instruments: Vocals,Guitar,Piano,name: Paul,instruments: Vocals,Bass,Piano,Guitar,name: George,instruments: Guitar,Vocals ,name: Ringo,instruments: Drums,Vocals ;Order 类的 toJSONObject()方法实现public JSONObject toJSONObject(

49、) JSONObject json = new JSONObject(); (id,id);(cost,getFormattedCost();(date,date);JSONArray jsonItems = new JSONArray(); for (lterator iter =();();)().toJSONObject();(items,jsonltems);return json;可以看到,API非常简单。JSONObject代表JavaScript 对象(即联合数组),有不同的put()方法,方法接受的Stri ng键和值是原生类型、String类型或其他JSON类型。JSONAr

50、ray代表索引数组,所以它的put()方法只接受一个值。请注意在清单8中,创建jsonItems 数组,然后再用 put()把它附加到json 对象上;可以用另外一种方法做这项工作,就是对每个项目调用(items,().toJSONObject(); 。accumulate。 方法 与put()类似,区别在于它把值添加到按照键进行识别的索引数组。清单9显示了如何序列化JSONObject并把它写入servlet 响应。清单9.从JSONObject生成序列化的JSON响应public void doGet(HttpServletRequest req, HttpServletResponse

51、res) throws ServletException String custId = (username);Customer customer = getCustomer(custId);(application/x-json);().print();可以看到,它实际上什么也没有做。在这里隐式调用的 JSONObject的toString()方法做了所有工作。请注意,applicatio n/x-json内容类型还有一点不确定在编写这篇文章的时候,关于JSON应当属于什么MIME类型还没有定论。但是,目前即plication/x-json是合理的选择。清单10显示了这个servlet 代码的示例响应。清单 10. Customer bea n 的 JSON 表示orders:items:price: $,description: 512 Megabyte Type 1 CompactFlash card.Manufactured b

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论