频道直达 - 专题 - 新闻 - 技巧 - 组网 - 开发 - 安全 - web编程 - 图像 - 操作系统 - 数据库 - 教育 - 旅游 - 健康 - 时尚 - 驱动 - 软件 - 游戏 - 多媒体 - ERP - 讨论组

在Ajax应用程序中实现数据交换

来源: 作者: 出处:巧巧读书 2006-07-28 进入讨论组
上一页 1 2 3 
谢 谢 收 藏 http://www.qqread.com/oracle/2006/08/e699190052.html

 

服务器端生成响应

    将 HTML 作为 Ajax 请求的响应而返回是一种最简单的解决方案,这是因为您可以使用 JSP 语法构建标记,而 Ajax 客户端只需使用 <div> 或 <span> 元素的 innerHTML 属性在页面某处插入 HTML。但是,向 Ajax 客户端返回不带任何表示标记的数据则更为有效。您可以使用 XML 格式或 JSON。

    生成 XML 响应。Java EE 提供了很多创建 XML 文档的选项:可通过 JSP 生成、通过 JAXB 从对象树创建、或利用 javax.xml.transform 生成。以下示例中的转换程序将串行化一个 DOM 树:

import javax.xml.transform.*;
import javax.xml.transform.dom.*;
import javax.xml.transform.stream.*;
...
public static TransformerFactory serializerFctory;
static {
serializerFctory = TransformerFactory.newInstance();
}
    
public static void serialize(Node node, OutputStream out)
throws TransformerException {
Transformer serializer = serializerFctory.newTransformer();
Properties serializerProps = new Properties();
serializerProps.put(OutputKeys.METHOD, "xml");
serializer.setOutputProperties(serializerProps);
Source source = new DOMSource(node);
Result result = new StreamResult(out);
serializer.transform(source, result);
}

    有这么多可在服务器端生成 XML 的标准选项和开发源框架,您唯一所要做的就是选择一个适合你的选项。但是,在客户端上,由于只能使用 DOM 来分析 XML,因此情况非常不同。某些浏览器还支持 XPath 和 XSLT。

    在先前的 Ajax 文章中,您学习了如何通过 JSP 生成 XML,然后在客户端上利用 JavaScript 和 DOM 对其进行分析。另一个解决方案是使用 JSON 而非 XML 作为响应 Ajax 请求的数据格式。如前所述,JSON 字符串可通过 eval() 函数转化为 JavaScript 对象树。较之利用 JavaScript 从 DOM 树提取信息而言,这更为简单些。您所需的就是一个在服务器端生成 JSON 的良好实用类。

JSON 编码。JSONEncoder 类提供了编码文字、对象和数组的方法。结果存储在 java.lang.StringBuilder 中:

package ajaxapp.util;

public class JSONEncoder {
private StringBuilder buf;
    
public JSONEncoder() {
buf = new StringBuilder();
    }

    ...
}

character() 方法编码单一字符:

public void character(char ch) {
switch (ch) {
case '\'':
case '\"':
case '\\':
buf.append('\\');
buf.append(ch);
break;
case '\t':
buf.append('\\');
buf.append('t');
break;
case '\r':
buf.append('\\');
buf.append('r');
break;
case '\n':
buf.append('\\');
buf.append('n');
break;
default:
if (ch >= 32 && ch < 128)
buf.append(ch);
else{
buf.append('\\');
buf.append('u');
for (int j = 12; j >= 0; j-=4) {
int k = (((int) ch) >> j) & 0x0f;
int c = k < 10 ?'0' + k :'a' + k - 10;
buf.append((char) c);
                }
            }
    }
}

string() 方法编码整个字符串:

public void string(String str) {
int length = str.length();
for (int i = 0; i < length; i++)
character(str.charAt(i));
}

literal() 方法编码 JavaScript 文字:

public void literal(Object value) {
if (value instanceof String) {
buf.append('"');
string((String) value);
buf.append('"');
} else if (value instanceof Character) {
buf.append('\'');
character(((Character) value).charValue());
buf.append('\'');
} else
buf.append(value.toString());
}

comma() 方法附加一个逗号字符:

private void comma() {
buf.append(',');
}

deleteLastComma() 方法将移除缓冲区末尾最后一个逗号字符(如果有的话):

private void deleteLastComma() {
if (buf.length() > 0)
if (buf.charAt(buf.length()-1) == ',')
buf.deleteCharAt(buf.length()-1);
}

startObject() 方法附加一个 { 字符,用于表示一个 JavaScript 对象的开始:

public void startObject() {
buf.append('{');
}

property() 方法编码 JavaScript 属性:

public void property(String name, Object value) {
buf.append(name);
buf.append(':');
literal(value);
comma();
}

endObject() 方法附加一个 } 字符,用于表示一个 JavaScript 对象的结束:

public void endObject() {
deleteLastComma();
buf.append('}');
comma();
}

startArray() 方法附加一个 [ 字符,用于表示一个 JavaScript 数组的开始:

public void startArray() {
buf.append('[');
}

element() 方法编码 JavaScript 数组的元素:

public void element(Object value) {
literal(value);
comma();
}

endArray() 方法附加一个 ] 字符,用于表示一个 JavaScript 数组的结束:

public void endArray() {
deleteLastComma();
buf.append(']');
comma();
}

toString() 方法返回 JSON 字符串:

public String toString() {
deleteLastComma();
return buf.toString();
}

clear() 方法清空缓冲区:

public void clear() {
buf.setLength(0);
}

DataModel 使用 JSONEncoder 类来编码其维护的数据:

public synchronized String getData() {
JSONEncoder json = new JSONEncoder();
json.startArray();
for (int i = 0; i < stockList.size(); i++) {
StockBean stock = stockList.get(i);
json.startObject();
json.property("symbol", stock.getSymbol());
json.property("shares", stock.getShares());
json.property("paidPrice", stock.getPaidPrice());
json.endObject();
    }
json.endArray();
return json.toString();
}

    如果提供了 xml 请求参数,则 ajaxCtrl.jsp 页面将设置模型的数据。否则,该页面会使用 ${dataModel.data} EL 表达式输出 getData() 返回的 JSON 字符串:

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
...
<jsp:useBean id="dataModel" scope="session"
class="ajaxapp.model.DataModel" />

<c:choose>
    ...
<c:when test="${!empty param.xml}">
<c:set target="${dataModel}" 
property="data" 
value="${param.xml}" />
</c:when>
<c:otherwise>
${dataModel.data}
</c:otherwise>
</c:choose>

这个作业并未完成,因为 Ajax 客户端必须处理 JSON 数据。

在客户端处理响应

    在典型的 Web 应用程序中,您使用 JSP、Web 框架和标记库在服务器端生成内容。Ajax 应用程序非常适合这种情况,因为 Web 框架(如 JavaServer Faces 和 Oracle ADF Faces)在构建 Ajax 应用程序时非常有用。然而,Ajax 和非 Ajax 应用程序之间仍然存在着明显不同。使用 Ajax 时,您必须在客户端处理数据,并用 JavaScript 动态生成内容来向用户提供数据。

    如果使用 JSON 格式进行数据转换,则使用 JavaScript 提供的 eval() 函数将文本转换为对象树非常容易。如果喜欢使用 XML,则还需要执行许多其他操作,但这种格式也有其自身的优势。例如,许多类型的客户端可以使用 XML,而 JSON 只在 JavaScript 环境中易于分析。此外,在使用 XML 的情况下,可以更快地发现并修正错误,从而缩短了调试时间。

    使用 JavaScript 访问 DOM 树。JavaScript 的 DOM API 非常类似于 Java 的 org.w3c.dom 程序包。主要的区别在于对属性的访问。在 JavaScript 中可直接访问属性,而 Java 将属性视为私有,您需要通过 get 和 set 方法进行访问。例如,您可通过 dom.documentElement 获得文档的根元素。

    DOM 是一种低级的 API,利用它可以访问已分析文档的结构。例如,在大多数情况下您都想忽略注释,并可能不愿意拥有相邻的文本节点。来看下面这个简单示例:

var xml = "<element>da<!--comment-->ta&"
+ "<![CDATA[cdata</element>";

您可以使用先前介绍的实用函数分析上述 XML 字符串:

var dom = parse(xml);

    您可以在 ajaxUtil.js 中找到 parse() 函数的代码;本例中,该函数返回一个 DOM 树,其根元素包含一个文本节点,其后是一条注释、另一个文本节点和一个字符数据节点。如果希望包含的文本不带注释,则必须迭代元素的子元素,连接文本和字符数据节点的值(其类型分别为 3 和 4):

var element = dom.documentElement;
var childNodes = element.childNodes;
var text = "";
for (var i = 0; i < childNodes.length; i++)
if (childNodes[i].nodeValue) {
var type = childNodes[i].nodeType;
if (type == 3 || type == 4)
text += childNodes[i].nodeValue;
    }

使用 DOM 时,应当构建一个小的实用函数集,以避免处理上述这些低级细节。

    使用 JavaScript 生成动态内容。Web 浏览器使您可以通过文档对象访问 Web 页面的 DOM 结构。例如,您可以利用 document.getElementById(...) 非常轻松地找到一个元素。还可以创建可插入现有文档的新元素和文本节点。然而,如下所示,通过连接字符串构建 HTML 要更为简单:

function updateInfo(request) {
var shares = eval(request.responseText);
var table = "<table border=1 cellpadding=5>";
table += "<tr>";
table += "<th>Symbol</th>";
table += "<th>Trend</th>";
table += "<th>Last Price</th>";
table += "</tr>";
for (var i = 0; i < shares.length; i++) {
var share = shares[i];
var symbol = escapeXML(share.symbol)
var trend = share.trend > 0 ? "+" : "-";
var lastPrice = new Number(share.lastPrice).toFixed(2);
table += "<tr>";
table += "<td>" + symbol + "</td>";
table += "<td>" + trend + "</td>";
table += "<td>" + lastPrice + "</td>";
table += "</tr>";
    }
table += "</table>";
document.getElementById("table").innerHTML = table;
}

通过设置由 getElementById() 返回的对象的 innerHTML 属性,可将生成的 HTML 插入空 <div> 元素中,例如:

<div id="table">
</div>

    本文的示例将 updateInfo() 函数用作回调来处理对 Ajax 请求的响应,该请求是通过 ajaxLogic.js 文件中的 sendInfoRequest 发送到服务器的。如果希望每 5 秒更新一次信息,可使用 JavaScript 的 setInterval() 函数:

var symbols = [ ... ];
setInterval("sendInfoRequest(symbols, updateInfo)", 5000);

    一个名为 DataFeed 的类模拟服务器端的馈送。ajaxCtrl.jsp 页面调用该馈送的 getData() 方法,将响应作为 JSON 字符串返回。在客户端,updateInfo() 函数利用 eval(request.responseText) 对该 JSON 字符串进行分析,如上述代码示例中所示。

结论

    在本文中,首先介绍了如何使用 URL 编码和 XML 格式从 Ajax 客户端向服务器传输数据。然后,阐释了如何通过 XML 模式验证数据、利用 XPath 提取所需信息以及在服务器端生成 XML 或 JSON 响应。最后,介绍了如何利用 JavaScript 处理 XML 和 JSON 响应,以及如何生成用于更新浏览器中 Web 页面的动态内容。

更多文章 更多内容请看Ajax技术专题Ajax技术应用开发Ajax入门与提高专题,或进入讨论组讨论。
上一页 1 2 3 
收藏此文】【 】【打印】【关闭
相关图文阅读
频道图文推荐
健 康 咨 询
时 尚 咨 询
巧巧读书宗旨
相关专题
讨论组问题推荐
站内各频道最新更新文档
站内最新制作专题
热门关键字导读
Photoshop教 程照片处理 照片制作 PS快捷键 抠图
计 算 机 故 障XP系统修复
艺 术 与 设 计设计 流媒体 设计欣赏 边框
计 算 机 安 全ARP
站内频道文章精选
巧巧电脑频道编辑信箱  告诉我们您想看的专题或文章