在Ajax 应用程序中实现数据之间交换
创建 XML 文档。利用字符串通过其属性和数据构建元素是用 JavaScript 创建 XML 文档最简单的方法。如果采用这种解决方案,则需要一个实用方法来转义 &、< 、>、"、以及 字符:
function escapeXML(content) {
if (content == undefined)
return "";
if (!content.length || !content.charAt)
content = new String(content);
var result = "";
var length = content.length;
for (var i = 0; i < length; i++) {
var ch = content.charAt(i);
switch (ch) {
case &:
result += "&";
break;
case < :
result += "< ";
break;
case >:
result += ">";
break;
case \":
result += """;
break;
case \\:
result += "'";
break;
default:
result += ch;
}
}
return result;
}
要使任务更为简单,还需要一些其他实用程序方法,例如:
function attribute(name, value) {
return " " + name + "=\"" + escapeXML(value) + "\"";
}
以下示例从一个具有以下三个属性的对象的数组构建一个 XML 文档:symbol、shares 和 paidPrice:
function buildPortfolioDoc(stocks) {
var xml = "< portfolio>";
for (var i = 0; i < stocks.length; i++) {
var stock = stocks[i];
xml += "< stock ";
xml += attribute("symbol", stock.symbol);
xml += attribute("shares", stock.shares);
xml += attribute("paidPrice", stock.paidPrice);
xml += "";
}
xml += "< /portfolio>";
return xml;
}
如果您喜好使用 DOM,则可使用 Web 浏览器的 API 分析 XML 和串行化 DOM 树。通过 IE,您可以用新的 ActiveXObject("Microsoft.XMLDOM") 创建一个空文档。然后,可以使用 loadXML() 或 load() 方法分别从字符串或 URL 分析该 XML。在使用 IE 的情况下,每个节点都有一个称为 xml 的属性,您可以利用它获得该节点及其所有子节点的 XML 表示。因此,您可以分析 XML 字符串、修改 DOM 树,然后将该 DOM 串行化回 XML。
Firefox 和 Netscape 浏览器允许您使用 document.implementation.createDocument(...) 创建一个空文档。然后,可以使用 createElement()、createTextNode()、createCDATASection() 等创建 DOM 节点。Mozilla 浏览器还提供了两个分别名为 DOMParser 和 XMLSerializer 的 API。DOMParser API 包含 parseFromStream() 和 parseFromString() 方法。XMLSerializer 类具有串行化 DOM 树的相应方法:serializeToStream() 和 serializeToString()。
以下函数分析一个 XML 字符串并返回 DOM 文档:
function parse(xml) {
var dom;
try{
dom = new ActiveXObject("Microsoft.XMLDOM");
dom.async = false;
dom.loadXML(xml);
} catch (error) {
try{
var parser = new DOMParser();
dom = parser.parseFromString(xml, "text/xml");
delete parser;
} catch (error2) {
if (debug)
alert("XML parsing is not supported.");
}
}
return dom;
}
第二个函数串行化一个 DOM 节点及其所有子节点,将 XML 作为字符串返回:
function serialize(dom) {
var xml = dom.xml;
if (xml == undefined) {
try{
var serializer = new XMLSerializer();
xml = serializer.serializeToString(dom);
delete serializer;
} catch (error) {
if (debug)
alert("DOM serialization is not supported.");
}
}
return xml;
}
还可以使用 XMLHttpRequest 作为分析程序或串行化程序。在从服务器接收到对 Ajax 请求的响应后,该响应会自动进行分析。可通过 XMLHttpRequest 的 responseText 和 responseXML 属性分别访问文本版本和 DOM 树。此外,在将 DOM 树传递至 send() 方法时自动将其串行化。
发送请求。在先前的文章中,我介绍了 XMLHttpRequest API 和一个实用函数 sendHttpRequest(),您可以在提供下载的示例中的 ajaxUtil.js 文件中找到。该函数有四个参数(HTTP 方法、URL、一个参数数组和一个回调),可创建 XMLHttpRequest 对象,设置其属性并调用 send() 方法。如果提供了回调参数,则异步发送请求,并在收到响应后调用回调函数。否则,将同步发送请求,您可以在 sendHttpRequest() 返回后即刻处理响应。
如您所见,在使用 XMLHttpRequest 时必须进行一些重要选择
将要使用的 HTTP 方法(GET 或 POST)
用于编码请求参数的格式(本文前面已探讨了 XML 和 URL 编码)
是进行同步(等待响应)调用还是异步(使用回调)调用
响应的格式,如 XML、XHTML、HTML 或 JavaScript Object Notation (JSON)(本文稍后将对此进行探讨)。假设您希望从数据馈送了解一些股价信息,且无需用户干预即可定期刷新信息。在本例中,应异步发送 HTTP 请求,这是为了在检索信息时不阻塞用户界面。请求参数是一个符号数组,可在 URL 中进行编码。由于服务器可能超载,因此您不希望在进行频繁请求时发送 XML 文档。由于您只对最新的股价感兴趣,因此应终止任何未完成的先前请求:
var ctrlURL = "ajaxCtrl.jsp";
var feedRequest = null;
function sendInfoRequest(symbols, callback) {
if (feedRequest)
abortRequest(feedRequest);
var params = new Array();
for (var i = 0; i < symbols.length; i++)
params[i] = {
name:"symbol",
value:symbols[i]
};
feedRequest = sendHttpRequest(
"GET", ctrlURL, params, callback);
}
在调用请求对象的 abort() 方法之前,abortRequest() 函数(可在 ajaxUtil.js 文件中找到)会将 onreadystatechange 属性设置为不执行任何操作的回调。此外,删除该请求对象以避免内存泄漏,这点至关重要:
function abortRequest(request) {
function doNothing() {
}
request.onreadystatechange = doNothing;
request.abort();
delete feedRequest;
}
我们来考虑另一种情况:在传输要保存在数据库中的整个用户数据时,应同步发送请求,因为您可能不希望用户在保存这些数据进行时对其进行修改。在这种情况下,首选 XML 格式,这是因为在文档中进行对象模型编码通常要比使用很多字符串参数更简单。此外,保存数据的请求并不频繁,服务器可以毫无问题地处理负载。可将 XML 文档编码为参数,这样您就可以使用 EL 语法 (${param.xml}) 在 JSP 页面中访问该文档了。以下就是发送在 XML 文档中编码的模型数据的函数:
function sendSaveRequest(xml) {
var params = [ { name:"xml", value:xml } ];
var saveRequest = sendHttpRequest("POST", ctrlURL, params);
if (saveRequest)
delete saveRequest;
}
如果需要恢复对象模型,则也可同步发送请求,从服务器检索数据。在这种情况下,服务器应当返回一个 JSON 响应,以便您可利用 eval(loadRequest.responseText) 轻松将其转换为 JavaScript 对象树:
function sendLoadRequest() {
var model = null;
var loadRequest = sendHttpRequest("GET", ctrlURL);
if (loadRequest) {
model = eval(loadRequest.responseText);
delete loadRequest;
}
return model;
}
以下两部分介绍了通常在服务器上对 XML 文档执行的操作,以及如何响应 Ajax 请求。
在服务器端处理请求
Servlet/JSP 容器分析各个 HTTP 请求并创建一个 ServletRequest 实例,该实例使您可以通过 getParameter() / getParameterValues() 获得请求参数,或通过 getInputStream() 获得请求正文。在 JSP 页面中,也可以使用 EL 语法(${param...} 和 ${paramValues...})获得这些参数。请注意,只有在 Ajax 客户端使用了类似于 buildQueryString() 之类的实用函数,通过 application/x-www-form-urlencoded 格式来编码数据(本文前一部分有述)的情况下,才可通过 getParameter() 或 ${param...} 获得请求参数。如果在客户端上将 XML 文档或 DOM 树传递至 XMLHttpRequest 的 send() 方法,则必须在服务器端使用 ServletRequest 的 getInputStream() 方法。
数据验证。典型的 Web 应用程序会进行许多数据验证操作。多数可能的错误相当简单,例如缺少请求参数、数字格式错误等等。这些错误通常是由于用户忘记输入表单元素的值或提供了无效值引起的。Web 框架(如 JSF 和 Oracle ADF Faces)非常善于处理这些用户错误。在 Ajax 应用程序中,这些错误可以在客户端使用 JavaScript 来捕获和处理。例如,您可使用 isNaN(new Number(value)) 验证数字值是否无效。




