异步JavaScript和XML(AJAX)与JavaEnterpriseEdition2006.11前言•使用过Flickr、GMail、GoogleSuggest或GoogleMaps的任何用户都会意识到,将出现一种新型的动态Web应用程序。这些应用程序的外观和作用与传统的桌面应用程序非常类似,它们不依赖于插件或特定于浏览器的功能。•传统的Web应用程序是一组HTML页,必须重新装入这些页面,才能更改内容的任何部分。在过去几年间,诸如JavaScript和层叠样式表(CSS)之类的技术已经发展成熟,可以有效地使用这些技术创建在所有主要浏览器上运行的动态性很强的Web应用程序。前言•本文档及其相关的解决方案将详细论述这几种技术,目前您可以使用这些技术使Web应用程序成为内容更丰富、交互性更强的应用程序,就像桌面应用程序一样异步JavaScript和XML(AJAX)简介1•HTML页使用JavaScript可以异步调用装入该页的服务器并获取XML文档。然后JavaScript可以使用XML文档更新或修改HTML页的文档对象模型(DOM)。•最近使用“异步JavaScript和XML”(AsynchronousJavaScriptandXML,AJAX)术语来描述此交互模型。异步JavaScript和XML(AJAX)简介2•AJAX不是一项新兴技术,对于在Windows平台上开发InternetExplorer(IE)的开发者来说,多年来他们一直在使用这些技术。直到最近,这项技术才被称为Web远程处理或远程脚本。一段时间以来,Web开发者还结合使用插件、JavaApplet和隐藏框架来仿真此交互模型。•而最近发生的变化就是:在所有平台的主流浏览器中都包含了对XMLHttpRequest对象的支持。真正的神奇之处在于产生了JavaScriptXMLHttpRequest对象。•虽然未在正式的JavaScript规范中指定此对象,但是目前所有的主流浏览器都支持它。与当前一代浏览器(如Firefox、IE和Safari)中的JavaScript和CSS支持稍有不同之处在于:它们是可管理的。如果要求您支持较旧的浏览器,则AJAX可能不是您的最佳选择。异步JavaScript和XML(AJAX)简介3•基于AJAX的客户端的独特之处在于,客户端包含了作为JavaScript嵌入的特定于页面的控制逻辑。页面基于事件(如装入的文档、鼠标单击、焦点更改,甚至是计时器)与JavaScript进行交互。•通过AJAX交互,可以清晰地将表示逻辑与数据分开。与每次要显示一个变化时必须重新装入整个页面相比,HTML页可以根据需要装入很小的数据片段。异步JavaScript和XML(AJAX)简介4•AJAX需要使用一种不同的服务器端体系结构来支持此交互模型。传统的服务器端Web应用程序着重为产生服务器调用的每个客户端事件生成HTML文档,并且在每次响应时客户端都会刷新并重新呈现完整的HTML页。•内容丰富的Web应用程序着重于获取HTML文档的客户端,该客户端充当一个模板或容器,根据客户端事件使用从服务器端组件检索的XML数据在其中添加内容。使用AJAX交互的用例1•实时的表单数据验证:在用户提交表单之前,可以在表单中验证要求服务器端验证的表单数据,如用户ID、序列号、邮政编码,甚至是特殊优惠券代码。•自动完成:表单数据的特定部分(如电子邮件地址、姓名或城市名称)可以在用户键入时自动完成。•主要详细操作:基于客户端事件,HTML页可以获取有关数据的更详细信息,例如,在不刷新页面的情况下,客户端可以查看个别产品信息的产品清单。使用AJAX交互的用例2•复杂的用户界面控件:可以提供不需要页面刷新的控件,如树状结构的控件、菜单和进度栏。•刷新页面上的数据:HTML页可以轮询服务器中的数据以获取最新的数据,如分数、股票报价、天气预报或特定于应用程序的数据。•服务器端通知:HTML页可以通过轮询服务器获取事件通知来模拟服务器端推送,包括发送消息通知客户端、刷新页面数据或将客户端重定向到其他页。使用AJAX交互的用例3•此列表并不详尽,但是它表明了利用AJAX交互,Web应用程序可以实现比以往更多的功能。尽管该技术有许多引人注目的优点,但是也存在一些缺点:•复杂性:服务器端开发者需要了解,在HTML客户端页以及服务器端逻辑中需要表示逻辑,才能生成客户端HTML页所需的XML内容。HTML页开发者需要具备JavaScript技术。随着时间的推移,当创建了新框架,并且为现有框架提供了交互模型支持后,创建支持AJAX的应用程序会变得更容易。使用AJAX交互的用例4•XMLHttpRequest对象的标准化:XMLHttpRequest还不是JavaScript规范的一部分,这表明其行为会随着客户端而发生变化。•JavaScript实现:AJAX交互在很大程度上依赖JavaScript(取决于客户端的不同而稍有差异),有关特定于浏览器的差异的详细信息,请访问QuirksMode.org。•调试:很难调试AJAX应用程序,这是因为在客户端和服务器中均嵌入了处理逻辑。•可查看的源文件:在客户端只需从支持AJAX的HTML页选择“查看源文件”,即可查看客户端JavaScript。如果基于AJAX的应用程序的设计很差,则可能会受到黑客或剽窃者的攻击。使用AJAX交互的用例5•随着开发者编写使用AJAX交互模型的应用程序的经验日益丰富,使用AJAX技术构建的各种框架和模式可能会纷纷出现。•在AJAX交互中强调“以部分更改适用全局更改”的框架仍然为时尚早,本文档着重说明现有的Java2EnterpriseEdition(J2EE)技术(如Servlet、JavaServerPages、JavaServerFaces和Java标准标记库(JSTL))目前是如何支持AJAX交互的。AJAX交互的分析1•到目前为止,已经论述了AJAX的含义以及存在的一些疑难问题,现在将所有内容结合起来演示支持AJAX的J2EE应用程序。•让我们来看一个示例,Web应用程序包含了一个静态HTML页,或者用JSP技术生成的HTML页,该页包含了一个HTML表单,要求服务器端逻辑验证表单数据而不刷新页面。名为ValidateServlet的服务器端Web组件(Servlet)将提供验证逻辑。下图描述了提供验证逻辑的AJAX交互的详细信息。AJAX交互图AJAX交互的分析2•下面的项表示了AJAX交互的设置,如上图显示的那样。–发生客户端事件。–创建并初始化XMLHttpRequest对象。–XMLHttpRequest对象发出调用。–请求由ValidationServlet进行处理。–ValidationServlet返回包含结果的XML文档。–XMLHttpRequest对象调用callback()函数并处理结果。–更新HTMLDOM。•现在让我们更详细地了解AJAX交互的每个步骤。1.发生客户端事件•调用JavaScript函数是事件产生的结果。在本例中,函数validate()会映射到链接或表单组件上的onkeyup事件。•inputtype=textsize=20id=useridname=idonkeyup=validate();•每次在表单字段中按下键时,上面的表单元素都将调用validate()。2.创建并初始化XMLHttpRequest对象1•初始化并配置XMLHttpRequest对象。varreq;functionvalidate(){varidField=document.getElementById(idField);varurl=validate?id=+escape(idField.value);if(window.XMLHttpRequest){req=newXMLHttpRequest();}elseif(window.ActiveXObject){req=newActiveXObject(Microsoft.XMLHTTP);}req.open(GET,url,true);req.onreadystatechange=callback;req.send(null);}创建并初始化XMLHttpRequest对象2•validate()函数会初始化XMLHttpRequest对象。open方法需要三个参数,即表示要使用的HTTP方法的GET或POST的url字符串、目标URL的字符串以及表明是否发出异步调用的布尔值。•如果将交互设置为异步(true),则必须指定回调函数。此交互的回调函数是使用语句req.onreadystatechange=callback;设置的。有关详细信息,请参见标题为“XMLHttpRequest对象调用callback()函数并处理结果”的部分。3.XMLHttpRequest对象发出调用1•执行到语句req.send(null);时,将发出调用。对于HTTP获得的内容可能是null或空值。为XMLHttpRequest对象调用此函数时,会调用初始化对象期间设置的URL。在本示例中,是以URL参数的形式包含传递的数据(id)。•当请求为幂等时(意味着两个重复的请求将返回相同的结果),请使用HTTPGET。使用HTTPGET方法时,包括转义的URL参数在内的URL长度受某些浏览器以及服务器端Web容器的限制。将数据发送到影响服务器端应用程序状态的服务器时,应该使用HTTPPOST方法。HTTPPOST要求使用以下语句为XMLHttpRequest对象设置Content-Type头:XMLHttpRequest对象发出调用2•通过JavaScript发送表单值时,应该考虑字段值的编码。JavaScript包括一个escape()函数,应该使用该函数确保对本地化的内容进行正确编码并且正确转义特殊字符。req.setRequestHeader(Content-Type,application/x-);req.send(id=+escape(idTextField.value));4.请求由ValidationServlet进行处理•映射到URI“验证”的Servlet会检查用户ID是否在用户数据库中。•Servlet就像处理任何其他HTTP请求那样处理XMLHttpRequest。下面的示例显示了一个服务器,该服务器从请求中提取id参数,并验证是否使用了该参数。publicclassValidationServletextendsHttpServlet{privateServletContextcontext;privateHashMapusers=newHashMap();publicvoidinit(ServletConfigconfig)throwsServletException{this.context=config.getServletContext();users.put(greg,accountdata);users.put(duke,accountdata);}publicvoiddoGet(HttpServletRequestrequest,HttpServletResponseresponse)throwsIOException,ServletException{StringtargetId=request.getParameter(id);if((targetId!=null)&&!users.containsKey(targetId.trim())){response.setContentType(text/xml);response.setHeader(Cache-Control,no-cache);response.getWriter().write(valid);}else{response.setContentType(text/xml);response.set