作为J2EE开发人员,我们似乎经常关注“后端机制(backend mechanics)”。我们通常会忘记,J2EE的主要成功之处在Web应用程序方面;许多原因使得人们喜欢利用Web开发应用程序,但主要还是因为其 易于部署的特点允许站点以尽可能低的成本拥有上百万的用户。遗憾的是,在过去几年中,我们在后端投入了太多的时间,而在使我们的Web用户界面对用户自然 和响应灵敏方面却投入不足。<o:p></o:p>
本文介绍一种方法,Ajax,使用它可以构建更为动态和响应更灵敏的Web应用程序。该方法的关键在于对浏览器端的JavaScript、 DHTML和与服务器异步通信的组合。本文也演示了启用这种方法是多么简单:利用一个Ajax框架(指DWR)构造一个应用程序,它直接从浏览器与后端服 务进行通信。如果使用得当,这种强大的力量可以使应用程序更加自然和响应灵敏,从而提升用户的浏览体验。<o:p></o:p>
该应用程序中所使用的示例代码已打包为单独的WAR文件,可供下载。<o:p></o:p>
简介<o:p></o:p>
术语Ajax用来描述一组技术,它使浏览器可以为用户提供更为自然的浏览体验。在Ajax之前,Web站点强制用户进入提交/等待/重新显示范 例,用户的动作总是与服务器的“思考时间”同步。Ajax提供与服务器异步通信的能力,从而使用户从请求/响应的循环中解脱出来。借助于Ajax,可以在 用户单击按钮时,使用JavaScript和DHTML立即更新UI,并向服务器发出异步请求,以执行更新或查询数据库。当请求返回时,就可以使用 JavaScript和CSS来相应地更新UI,而不是刷新整个页面。最重要的是,用户甚至不知道浏览器正在与服务器通信:Web站点看起来是即时响应 的。<o:p></o:p>
虽然Ajax所需的基础架构已经出现了一段时间,但直到最近异步请求的真正威力才得到利用。能够拥有一个响应极其灵敏的Web站点确实激动人 心,因为它最终允许开发人员和设计人员使用标准的HTML/CSS/JavaScript堆栈创建“桌面风格的(desktop-like)”可用性。<o:p></o:p>
通常,在J2EE中,开发人员过于关注服务和持久性层的开发,以至于用户界面的可用性已经落后。在一个典型的J2EE开发周期中,常常会听到这样的话,“我们没有可投入UI的时间”或“不能用HTML实现”。但是,以下Web站点证明,这些理由再也站不住脚了:<o:p></o:p>
所有这些Web站点都告诉我们,Web应用程序不必完全依赖于从服务器重新载入页面来向用户呈现更改。一切似乎就在瞬间发生。简而言之,在涉及到用户界面的响应灵敏度时,基准设得更高了。<o:p></o:p>
定义Ajax<o:p></o:p>
Adaptive Path公司的Jesse James Garrett这样定义Ajax:<o:p></o:p>
Ajax不是一种技术。实际上,它由几种蓬勃发展的技术以新的强大方式组合而成。Ajax包含:<o:p></o:p>
这非常好,但为什么要以Ajax命名呢?其实术语Ajax是由Jesse James Garrett创造的,他说它是“Asynchronous JavaScript + XML的简写”。<o:p></o:p>
Ajax的工作原理<o:p></o:p>
Ajax的核心是JavaScript对象XmlHttpRequest。该对象在Internet Explorer 5中首次引入,它是一种支持异步请求的技术。简而言之,XmlHttpRequest使您可以使用JavaScript向服务器提出请求并处理响应,而不 阻塞用户。<o:p></o:p>
在创建Web站点时,在客户端执行屏幕更新为用户提供了很大的灵活性。下面是使用Ajax可以完成的功能:<o:p></o:p>
一切皆有可能!但愿它能够激发您开始开发自己的基于Ajax的站点。然而,在开始之前,让我们介绍一个现有的Web站点,它遵循传统的提交/等待/重新显示的范例,我们还将讨论Ajax如何提升用户体验。<o:p></o:p>
Ajax可用于那些场景?——一个例子:MSN Money页面<o:p></o:p>
前几天,在浏览MSN Money页面的时候,有一篇关于房地产投资的文章引起了我的好奇心。我决定使用站点的“Rate this article”(评价本文)功能,鼓励其他的用户花一点时间来阅读这篇文章。在我单击vote按钮并等待了一会儿之后,整个页面被刷新,在原来投票问题所在的地方出现了一个漂亮的感谢画面。<o:p></o:p>
<v:shapetype o:spt="75" coordsize="21600,21600" filled="f" stroked="f" id="_x0000_t75" path="m@4@5l@4@11@9@11@9@5xe" o:preferrelative="t"><v:stroke joinstyle="miter"></v:stroke><v:formulas><v:f eqn="if lineDrawn pixelLineWidth 0"></v:f><v:f eqn="sum @0 1 0"></v:f><v:f eqn="sum 0 0 @1"></v:f><v:f eqn="prod @2 1 2"></v:f><v:f eqn="prod @3 21600 pixelWidth"></v:f><v:f eqn="prod @3 21600 pixelHeight"></v:f><v:f eqn="sum @0 0 1"></v:f><v:f eqn="prod @6 1 2"></v:f><v:f eqn="prod @7 21600 pixelWidth"></v:f><v:f eqn="sum @8 21600 0"></v:f><v:f eqn="prod @7 21600 pixelHeight"></v:f><v:f eqn="sum @10 21600 0"></v:f></v:formulas><v:path o:extrusionok="f" o:connecttype="rect" gradientshapeok="t"></v:path><o:lock v:ext="edit" aspectratio="t"></o:lock></v:shapetype><v:shape id="_x0000_i1025" type="#_x0000_t75" alt="" style="WIDTH: 227.25pt; HEIGHT: 47.25pt"><v:imagedata o:href="http://dev2dev.bea.com.cn/images/051101/0511010101.jpg" src="file:///C:\DOCUME~1\zx\LOCALS~1\Temp\msohtml1\01\clip_image001.jpg"></v:imagedata></v:shape><o:p></o:p>
而Ajax能够使用户的体验更加愉快,它可以提供响应更加灵敏的UI,并消除页面刷新所带来的闪烁。目前,由于要刷新整个页面,需要传送大量的 数据,因为必须重新发送整个页面。如果使用Ajax,服务器可以返回一个包含了感谢信息的500字节的消息,而不是发送26,813字节的消息来刷新整个 页面。即使使用的是高速Internet,传送26K和1/2K的差别也非常大。同样重要的是,只需要刷新与投票相关的一小节,而不是刷新整个屏幕。<o:p></o:p>
让我们利用Ajax实现自己的基本投票系统。<o:p></o:p>
原始的Ajax:直接使用XmlHttpRequest<o:p></o:p>
如上所述,Ajax的核心是JavaScript对象XmlHttpRequest。下面的示例文章评价系统将带您熟悉Ajax的底层基本知识:http://tearesolutions.com/ajax-demo/raw-ajax.html。注:如果您已经在本地WebLogic容器中安装了ajax-demo.war,可以导航到http://localhost:7001/ajax-demo/raw-ajax.html,<o:p></o:p>
浏览应用程序,参与投票,并亲眼看它如何运转。熟悉了该应用程序之后,继续阅读,进一步了解其工作原理细节。<o:p></o:p>
首先,您拥有一些简单的定位点标记,它连接到一个JavaScriptcastVote(rank)函数。 <o:p></o:p>
function castVote(rank) {<o:p></o:p>
var url = "/ajax-demo/static-article-ranking.html";<o:p></o:p>
var callback = processAjaxResponse;<o:p></o:p>
executeXhr(callback, url);<o:p></o:p>
}<o:p></o:p>
该函数为您想要与之通信的服务器资源创建一个URL并调用内部函数executeXhr,提供一个回调JavaScript函数,一旦服务器响 应可用,该函数就被执行。由于我希望它运行在一个简单的Apache环境中,“cast vote URL”只是一个简单的HTML页面。在实际情况中,被调用的URL将记录票数并动态地呈现包含投票总数的响应。<o:p></o:p>
下一步是发出一个XmlHttpRequest请求: <o:p></o:p>
function executeXhr(callback, url) {<o:p></o:p>
// branch for native XMLHttpRequest object<o:p></o:p>
if (window.XMLHttpRequest) {<o:p></o:p>
req = new XMLHttpRequest();<o:p></o:p>
req.onreadystatechange = callback;<o:p></o:p>
req.open("GET", url, true);<o:p></o:p>
req.send(null);<o:p></o:p>
} // branch for IE/Windows ActiveX version<o:p></o:p>
else if (window.ActiveXObject) {<o:p></o:p>
req = new ActiveXObject("Microsoft.XMLHTTP");<o:p></o:p>
if (req) {<o:p></o:p>
req.onreadystatechange = callback;<o:p></o:p>
req.open("GET", url, true);<o:p></o:p>
req.send();<o:p></o:p>
}<o:p></o:p>
}<o:p></o:p>
}<o:p></o:p>
<o:p><fo>