AJAX设计策略(全)
内容
-概况
-什么是AJAX
-AJAX技术
-AJAX和服务端技术
-设计策略
-设计策略1:自己完成(Do It Yourself)
-设计策略2:使用客户端JavaScript库
-设计策略3:使用客户端框架
-设计策略4:包装
-设计策略5:远程调用
-设计策略6:所有Java技术
-其他信息
-关于作者
概况
受网站目标的驱使,Web应用已经进入了一个新时代,这些目标包括更快的响应用户动作,在创作和分享web内容时进行的用户协作等。被定义为此类高速响应的和经常协作站点的最流行的术语就是Web 2.0。
|
|
|
一些web 2.0的最经典的例子包括Google Maps 和 Flickr站点。Google Maps提供一个高速响应的用户界面(UI)。例如:你可以察看一副地图,并通过移动鼠标越过它以立即的察看相临近的区域。Flickr是这样一个网站,用户们存储和共享照片--用户管理几乎这个站点的所有内容。
另外的Web2.0站点通过一些方式提供相似的丰富的用户体验,这些方式包括整合其他网站的服务或合并一个稳定的新的信息流。例如,Google map服务可以被使用在另一个站点,比如一个汽车销售站点,用来显示一家销售指定汽车类型的代理商在地图上的位置。此类站点集成使用的术语叫做” mashups”。另外还包括一个运动导向网站,它可以不断的刷新分数而不需要用户请求页面更新。
这篇文章是关于现今用来制作高响应的web 2.0站点的主要技术:Asynchronous JavaScript and XML (AJAX).
什么是AJAX?
许多优秀的文章都将AJAX描述为有效的,例如《Asynchronous JavaScript Technology and XML (AJAX) With Java 2 Platform Enterprise Edition》。简单说,AJAX是一系列使网页成为-或看起来像高速响应的技术。AJAX使这个成为可能,因为它支持网页的异步和部分刷新功能。
部分刷新意味着当一个交互事件发生-例如,用户向网页的表单里输入信息并且点击提交按钮-服务器处理信息并返回关于这些信息的有限响应。值得注意的,服务器并不返回整个页面,虽然返回整个页面已成为一种惯例,“点击,等待,刷新”web应用。相反的,客户端基于响应来更新页面。这意味着,只有部分页面被更新。换句话说,网页像一个模版一样被处理:客户端和服务端交换数据,客户端基于收到的数据来更新模版的某部分。可以这样认为,使用AJAX的web应用受事件和数据的驱动,而传统的web应用受页面驱动。
异步意味着在向服务端发送数据之后,当服务端在后台运行的时候,客户端可以继续执行。这意味这用户可以继续与客户端进行交互,而不必等待服务端的滞后响应。例如,用户可以继续在Google map上移动鼠标,并在显示器上看到一个平滑的,不间断的变换。客户端在继续执行之前不必等待服务端的响应。
AJAX站点的另一个重要方面在于,触发AJAX响应的事件不限于提交数据或点击链接。在页面的一个区域上移动鼠标,在输入域中键入数据,或者像Google Maps一样用鼠标拖拽地图,已足够触发AJAX响应。用户和网页间的动态交互使web应用更接近于高速响应的桌面应用。桌面应用经常被称为胖桌面应用(rich desktop applications)。所以web 2.0经常被叫做胖互联网应用(rich Internet applications)。
AJAX技术
下面的技术是AJAX里具有代表性的:
层叠样式单(CSS),一种定义页面表示样式的语言,例如字体、颜色等。
JavaScript,一种脚本语言。在JavaScript技术里对AJAX很关键的一个元素是XMLHttpRequest,一个用来在web客户端和web服务端交换数据的对象。
文档对象模型(DOM),提供页面的树状结构的逻辑视图。
XML,用来从服务端向客户端传送数据的一种格式。尽管如此,你可以使用其他格式,例如HTML, JavaScript Object Notation (JSON), 或无格式文本.
像其他web应用一样,AJAX web应用使用HTML,XHTML类的标记语言来呈现页面,或者JSP类服务端技术来生成网页。另外,服务端应用系统在AJAX应用中扮演一个关键的角色。类似Java EE的服务端应用系统包括对关于AJAX的数据验证,用户身份管理,和持久性配置的很好支持。请看本文的AJAX and Server-Side Java Technologies部分。
| |
|
图1: AJAX 如何处理用户动作 |
1. 用户在客户端生成一个事件。这导致了一个JavaScript调用。
2. JavaScript函数在客户端创建和设定一个XMLHttpRequest对象,并且指定一个JavaScript回调函数。
3. XMLHttpRequest对象向web服务端生成一个调用—一个异步的HTTP请求。
4. web 服务端处理请求并且返回一个包含结果的XML文档。
5. XMLHttpRequest对象调用回调函数,呈现服务端的响应使得请求得到处理。
6. 客户端使用新数据更新描述页面的HTML DOM。
你可以通过多种方法将这些技术整合到web应用。例如,你可以在HTML页面里写JavaScript代码,或者你可以使用Dojo toolkit之类的库,它会提供你需要的部分或者全部的JavaScript功能。另外,你还有关于AJAX的服务器端的选择。
AJAX和服务器端JAVA技术
所有的AJAX技术,同时也是客户端技术例如JavaScript、XML,都是关于客户端和服务端交互数据的。事实上XMLHttpRequest对象向服务端创建的请求是一个HTTP请求。对服务端来说,处理AJAX请求和处理传统web应用的HTTP请求没有不同-任何服务端技术都可以处理请求,包括Java EE的服务端java技术例如servlets,JSP技术,和JavaServer Faces技术。事实上,Java EE非常适合AJAX方法。JavaServer Faces和包含支持数据验证,用户身份管理,持久性的其他Java EE技术,非常适合于AJAX。
例如,你可以用servlet处理请求,管理客户端状态,访问企业资源,并为响应生成XML。或者你可以创建定制的JavaServer Faces组件进行服务端处理,也可以封装处理客户端的Javascript和CSS。
设计策略
作为开发者,你有很多个将AJAX置入web应用的选项。这些选项范围涉及从自己编写所有AJAX代码的DIY策略,到利用可以为你提供AJAX代码的库和框架。你可以多种策略。例如,你可以使用基于JavaServer Faces的客户端-服务端框架,并结合客户端的javascript库例如Dojo工具箱。
本文的剩余部分将讨论这样的一些设计策略并鉴定他们的优势的缺点。这些策略假定你在服务器端使用Java EE实现,例如Sun Java Application Server。
设计策略1:自己完成(Do It Yourself)
走这条路,你自己编写所有代码来将AJAX置入web应用。这意味着你将编写客户端的所有JavaScrip, CSS, and DOM代码,和关于页面呈现的代码。在服务端,你编写处理XMLHttpRequest调用的代码,并返回适当的响应,比如XML。
让我们看一个将AJAX功能加入web应用的例子。例子发表在文章"Creating an AJAX-Enabled Bookstore Application, a Do-It-Yourself Approach"上。它那个例子基于bookstore2,是Java EE 5 Tutorial中Duke's Bookstore例子的其中一个。你可以在Java EE 5 Tutorial的The Example JSP Pages部分找到创建bookstore2 web应用的说明。
最初的bookstore2web 表列了可以购买的书籍。用户和现在的bookstore2应用和交互是一个传统的同步交互。用户点击列表里书的标题进一步察看这本书的更多信息。这需要服务端完成所有的页面刷新。
这个发标在文章"Creating an AJAX-Enabled Bookstore Application"的例子添加了一些AJAX功能,是web应用能够弹出气球。添加的功能提供了更多的动态UI。当用户将鼠标越过表列的书目,关于书的细节将出现在弹出气球上,如图2所示。由于它是受AJAX驱动的,产生气球的用户和web应用间的交互是异步的。用户几乎即时的看到弹出气球-不需要等待服务端刷新整个页面。
|
图2: 一个AJAX弹出式气球的web应用 |
回忆图1的步骤,在这里,bookstore2 web应用程序中AJAX的相关代码
1. 将事件映射到一个JavaScript 函数
2. 创建和配置XMLHttpRequest对象
3. 通过XMLHttpRequest对象向服务端创建一个请求
4. 在服务端处理请求并返回一个包含结果的XML文档
5. 在JavaScript callback()函数中处理结果
6. 更新DOM用新数据呈现页面
附随"Creating an AJAX-Enabled Bookstore Application"这篇文章的是AJAX bookstore2应用程序文件。这些文件打包为一个NetBeans IDE 5.5 web应用项目。这篇文章将向你展示怎样打开和运行使用NetBeans IDE 5.5的项目。同时也展示怎样察看这些文件的内容。使用NetBeans IDE 5.5,你可以看到列出的每一步在代码是怎样实现的。
你会发现程序代码的主要部分是客户端JavaScript代码。例如,这里有一些bookstore2程序的JavaScript代码,它们创建和并配置了一个XMLHttpRequest对象,并用它向服务端组件创建了一个异步的请求。
|
bpui.alone.showPopupInternal=function(popupx, bookId) {
bpui.alone.req=bpui.alone.initRequest();
...
url="../PopupServlet?bookId=" + escape(bookId);
bpui.alone.req.onreadystatechange = bpui.alone.ajaxReturnFunction;
bpui.alone.req.open("GET", url, true);
bpui.alone.req.send(null);
}
...
bpui.alone.initRequest=function() {
if (window.XMLHttpRequest) {
return new XMLHttpRequest();
} else if (window.ActiveXObject) {
return new ActiveXObject("Microsoft.XMLHTTP");
}
} |
这里有JavaScript回调函数,处理异步请求响应的数据。注意,回调函数使用类似getElementsByTagName()的DOM API方法来提取XML中的数据。inner.HTML属性被用来更新页面的DOM呈现。
|
bpui.alone.ajaxReturnFunction=function() {
// statically setup popup for simple case
var componentId="pop0";
// check return of the call to make sure it is valid
if (bpui.alone.req.readyState == 4) {
if (bpui.alone.req.status == 200) {
// get results and replace dom elements
var resultx=bpui.alone.req.responseXML.getElementsByTagName("response")[0];
document.getElementById(componentId + "_title").innerHTML=
resultx.getElementsByTagName("title")[0].childNodes[0].nodeValue;
document.getElementById(componentId + "_message").innerHTML=
resultx.getElementsByTagName("message")[0].childNodes[0].nodeValue;;
// show popup with the newly populated information
document.getElementById(componentId).style.visibility='visible';
} else if (bpui.alone.req.status == 204){
alert("204 returned from AJAX call");
}
}
} |
AJAX bookstore2程序同样需要包含服务端组件的代码,例如servlet-处理XMLHttpRequest并返回适当的响应。"Creating an AJAX-Enabled Bookstore Application"这篇文章同样分析servlet代码,和其他关于弹出式气球文件里的代码。
简言之,do-it-yourself方式需要编写很大数量的AJAX相关代码来实现bookstore2程序的弹出式气球-其中有一些相当复杂。
Do-It-Yourself方法的正面和反面
do-it-yourself approach方法的确是将AJAX置入web应用的一种方法,但是它是最适合你的方法吗?这里有一些使用这种方法的优势(正面)和劣势(反面)。
正面
在AJAX处理上提供细密的控制,当你宁愿编写所有的AJAX相关代码而不使用JavaScript库或者其他能提供AJAX功能的方法,你可以明确的控制AJAX相关处理。你可以包含库没有提供或定制的功能,可以通过最适合你的方法使你的AJAX代码最优化。例如,你可以添加安全性控制或为性能而优化代码。
反面
需要很多的AJAX相关代码。如果你分析bookstore2里的代码,你将发现它需要很少的AJAX相关代码。如果其他方法提供你需要的AJAX功能并且需要很少代码,根据感觉使用这些方法。例如,类似在Dojo工具箱中的客户端JavaScript库,封装了一些类似创建和配置XMLHttpObject的AJAX操作,它们将减少你所需要编写的代码。如果库可以提供你需要的AJAX功能,使用它会比编码实现功能简单很多。请查阅本文的Design Strategy 2: Use a Client-Side JavaScript Technology Library部分。
需要若干种语言和技术的知识。AJAX代码需要你懂得JavaScript,CSS,和DOM-这些对Java工程师来说并不是必须要懂的。其他方法,例如使用jMaki技术,允许你使用基于Java的技术整合AJAX功能。请看Design Strategy 4: Do the Wrap Thing部分。
需要开发者与浏览器的不兼容性斗争。尽管现在大多数的浏览器可以处理AJAX代码,不是所有的浏览器使用同一种方法处理AJAX代码。特别的,很多浏览器处理JavaScript代码的方式不同。值得注意的,对象XMLHttpRequest并不是JavaScript标准的一部分。事实上,IE现在并不支持XMLHttpRequest对象。而是用ActiveX控件同服务器进行AJAX通信。这就是bpui.alone.initRequest()函数为什么包含下面的测试:
另外,你必须考虑浏览器不支持AJAX的所有可能性,例如一些老版本的浏览器。另一种办法,例如使用客户端JavaScript库,jMaki, Direct Web Remoting (DWR), 和 the Google Web Toolkit (GWT)会处理浏览器的不兼容性。请看本文的Design Strategy 5: Go Remote部分。
需要开发者与UI问题做斗争。AJAX web应用引入了许多UI问题。例如,你怎样为一个AJAX网页支持书签,如果他的内容经常改变但URL不会。你怎样为一个页面的特定状态做书签。另外,你怎样支持后退按钮?另一个简单的应用,开发者必须考虑这些UI问题并编写处理它们的代码。客户端JavaScript库,例如那些在Dojo toolkit, Prototype, 和 Script.aculo.us中提供的,包含了处理那些问题的特性。
难以调试。由于AJAX代码分配在客户端和服务端之间, JavaScript, DOM, CSS 等的多种类型代码的结合,调试AJAX代码会很困难。
需要开发者与UI问题做斗争。AJAX web应用引入了许多UI问题。例如,你怎样为一个AJAX网页支持书签,如果他的内容经常改变但URL不会。你怎样为一个页面的特定状态做书签。另外,你怎样支持后退按钮?另一个简单的应用,开发者必须考虑这些UI问题并编写处理它们的代码。客户端JavaScript库,例如那些在Dojo toolkit, Prototype, 和 Script.aculo.us中提供的,包含了处理那些问题的特性。
难以调试。由于AJAX代码分配在客户端和服务端之间, JavaScript, DOM, CSS 等的多种类型代码的结合,调试AJAX代码会很困难。
幸运的,新的调试工具例如Mozilla Firebug调试器正在出现,以使调试AJAX代码更加简单。GWT也提供调试客户端和服务端代码的环境。请看本文的Design Strategy 6: Go All Java Technology部分。
暴露JavaScript代码-一个潜在的安全问题。在web应用客户端上的的JavaScript代码是看的见的。包括黑客在内的任何人可以看见并分析浏览器页面上的源代码。危害会随之而来。他们可能试图相反的操纵你的web应用。他们甚至可以从你的web应用上劫持XMLHttpRequests并返回破坏性的响应。
设计策略2:使用客户端JavaScript库
无须为AJAX应用编写所有的客户端JavaScript代码,你可以利用JavaScript库的优势,他们提供AJAX功能,例如: Dojo toolkit, Prototype, Script.aculo.us, 和Rico。要找其他的,请见Survey of AJAX/JavaScript Libraries.
Dojo toolkit是一个开源的JavaScript工具箱,它的库和API可以轻松的将AJAX置入web应用。例如,dojo.io库抽象化同服务端的AJAX通信,所以隐藏了底层的XMLHttpRequest操作。使用XMLHttpRequest库,AJAX bookstore2应用程序中的bpui.alone.showPopupInternal()函数将会变成这样:
dojo.require("dojo.io.*");
...
// This function is called after initial timeout that represents the delay
bpui.alone.showPopupInternal=function(popupx, bookId) {
// retrieve data through dojo call
var bindArgs = {
url: "../PopupServlet?bookId=" + escape(bookId),
mimetype: "text/xml",
load: bpui.alone.ajaxReturnFunction};
// dispatch the request
bpui.alone.req=dojo.io.bind(bindArgs);
dojo.require()函数动态的为指定的库装载JavaScript代码,这里是dojo.io库。更新的bpui.alone.showPopupInternal()函数使用dojo.io.bind()方法向服务端提交一个异步的请求。bind()方法包装了XMLHttpRequest,因此你不必再像do-it-yourself方式那样创建和配置XMLHttpRequest对象。你需要为bind()方法提供以下参数:与之通话的服务端组件的URL,响应的格式,和回调函数标识。你也可以指定其他的参数,如error。
Dojo toolkit中的其他库提供多种API,可以使编码变得简单,例如:动画,DOM操作,拖拽支持,UI效果。另外,工具箱提供完善的事件处理机制。尽管如此,Dojo toolkit由于他的内置窗口部件库而闻名,你可以预创建UI组件,然后将它插入web应用并根据需要定制它。Dojo窗口部件能让你创建自己的部件。
Prototype是一个JavaScript框架。它提供一个库,库的构件包含能使JavaScript应用简易化的对象。其中一个构建提供一个AJAX对象,类似Dojo toolkit中的dojo.io库,封装了XMLHttpRequest对象并隐藏了XMLHttpRequest操作。另一个构件提供一些对象和方法可以使操作DOM更简单。
Script.aculo.us 和 Rico是在Prototype的基础上建立的。二者都提供支持AJAX,拖拉,UI效果,和其他插入web应用功能的JavaScript库。
使用客户端JavaScript库的正面和反面
这里有一些使用客户端JavaScript库建立AJAX web应用的正面和反面。
正面
隐藏底层细节。Dojo toolkit中的dojo.io库、Prototype库,此类库都封装了AJAX的一些细节。包括创建和配置XMLHttpRequest对象,和在这些对象上执行的一些操作。这些库允许你在一个更高、更抽象的层次上编码,使你不必提供更多的细节代码。
减少JavaScript编码的需要。Dojo toolkit DOM manipulation或者Prototype DOM manipulation之类的库提供例行程序,可以方便的被使用并且比起他们的等价的JavaScript库需要更少的代码。另外,组装类似Dojo toolkit里预建的窗口部件要比编写JavaScript功能简单的多。
进行AJAX的时候处理浏览器的不兼容性。客户端JavaScript库类似Dojo toolkit中的那些,隐藏了很多不同浏览器处理AJAX的不同方法。例如,dojo.io.bind()方法请求封装了XMLHttpRequest,可以处理IE创建异步请求时的不同。Prototype为DOM操作提供的对象隐藏了浏览器处理DOM相关操作时的不同。另外,客户端JavaScript库包含了功能退化("graceful degradation")特性,以处理AJAX不能支持的情况-使你不必编写代码来应对那种可能性。
处理一些常见的AJAX问题,比如书签和后退按钮支持。众多的客户端JavaScript库提供书签和后退按钮的支持。例如,你可以通过将dojo.io.bind()的changeURL参数设为true就可以轻易的为bookstore2程序添加书签支持。
dojo.require("dojo.io.*");
...
// This function is called after initial timeout that represents the delay
bpui.alone.showPopupInternal=function(popupx, bookId) {
// retrieve data through dojo call
var bindArgs = {
url: "../PopupServlet?bookId=" + escape(bookId),
mimetype: "text/xml",
load: bpui.alone.ajaxReturnFunction};
changeURL:true;
// dispatch the request
bpui.alone.req=dojo.io.bind(bindArgs);
为这些工具设立的用户社区可以帮助回答疑问。类似Dojo toolkit的著名客户端库拥有著名的用户社区,通过基于社区的论坛和博客提供支持和帮助。另外,Dojo之类的开源库社区参与进行对库的扩展和增强。这包括公司的支持和贡献。例如,Dojo基金会,一个为促进使用Dojo 和 JavaScript而设立的非盈利性组织,获得了IBM 和 Sun Microsystems公司等的赞助和积极协助。
反面
需要一些JavaScript知识。客户端JavaScript库不能排除对JavaScript编码的需要。最多降低了编写JavaScript代码的需要。在更新的bookstore2例子里,使用Dojo toolkit排除了编码创建、配置和使用XMLHttpRequest对象的需要,但你同样要编码调用封装了XMLHttpRequest请求的dojo.io.bind()函数。
可能需要混合和匹配JavaScript库。这可以被看作优点和缺点。如果一个单独的JavaScript库不能给你所需的功能,你可以灵活的从其他的JavaScript库获得另外的功能,从同一个或这另一个工具箱里。不会限制你只能在web应用里使用一个客户端JavaScript库。例如,你可以使用Prototype对象来同服务端进行AJAX通信,使用Dojo toolkit里的窗口部件实现UI。灵活是一件好事。尽管如此,不同的客户端库来源有自己语法结构,所以你需要学习使用这些库的不同方法。
可能无法满足所有的AJAX需求。有这种可能性,客户端JavaScript库不会满足所有的将AJAX置入web应用的JavaScript需要。因此你需要另一种方法来满足其他的需求。
[1] [2]
编辑 webmaster








