这个例子是《Ajax基础教程》上面的,我自己稍微做了点修改。利用xmlHttpRequest对象不断刷新页面上指定位置的内容,但不用刷新整个页面。点击"Launch"开始自动更新,更新完毕显示"Done!",然后可以点击"Clear"清除更新的内容,或者再次点击"Launch"开始下一次更新。
dynamicUpdate.jsp:
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta. http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Dynamic Update Test</title>
<script>
var xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
function doStart() {
document.getElementById("go").disabled = true;
document.getElementById("clear").disabled = true;
var url = "DynamicUpdateServlet?task=reset";
xmlHttp.open("GET", url, true);
xmlHttp.onreadystatechange = startCallback;
xmlHttp.send(null);
}
function startCallback() {
if (xmlHttp.readyState == 4) {
if (xmlHttp.status == 200) {
setTimeout("pollServer()", 2000);
refreshTime();
}
}
}
function refreshTime() {
var time_span = document.getElementById("time");
var time_val = time_span.innerHTML;
var new_int_val = time_val * 1 - 1;
if (new_int_val > -1) {
setTimeout("refreshTime()", 1000);
time_span.innerHTML = new_int_val;
} else {
time_span.innerHTML = 2;
}
}
function pollServer() {
var url = "DynamicUpdateServlet?task=foo";
xmlHttp.open("GET", url, true);
xmlHttp.onreadystatechange = pollCallback;
xmlHttp.send(null);
}
function pollCallback() {
if (xmlHttp.readyState == 4) {
if (xmlHttp.status == 200) {
var message = xmlHttp.responseXML.getElementsByTagName("message")[0].firstChild.data;
var new_row = createRow(message);
var table = document.getElementById("dynamicUpdateArea");
var table_body = table.getElementsByTagName("tbody").item(0);
var first_row = table_body.getElementsByTagName("tr").item(1);
table_body.insertBefore(new_row, first_row);
if (message != "Done!") {
setTimeout("pollServer()", 2000);
refreshTime();
} else {
document.getElementById("go").disabled = false;
document.getElementById("clear").disabled = false;
}
}
}
}
function createRow(message) {
var row = document.createElement("tr");
var cell = document.createElement("td");
var cell_data = document.createTextNode(message);
cell.appendChild(cell_data);
row.appendChild(cell);
return row;
}
function clearRows() {
var rows = document.getElementsByTagName("tbody")[0].childNodes;
var container = document.getElementsByTagName("tbody").item(0);
while(container.hasChildNodes()) {
container.removeChild(rows[1]);
}
}
</script>
</head>
<body>
<h1>Ajax Dynamic Update Example</h1><br/>
The page will automatically update itself:
<input type="button" value="Launch" id="go" onclick="doStart();" />
<input type="button" value="Clear" id="clear" onclick="clearRows();" /><br/>
Page will refresh in <span id="time"> 2 </span> seconds.<br/>
<table id="dynamicUpdateArea" align="left" >
<tbody>
<tr id="row0">
<td></td>
</tr>
</tbody>
</table><br/>
</body>
</html>
DynamicUpdateServlet.java:
package src;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class DynamicUpdateServlet extends javax.servlet.http.HttpServlet implements javax.servlet.Servlet {
private int counter = 1;
public DynamicUpdateServlet() {
super();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/xml");
response.setHeader("Cache-Control", "no-cache");
String res= "";
String task = request.getParameter("task");
String message = "Start";
if (task.equals("reset")) {
counter = 1;
} else {
switch (counter) {
case 1: message = "This is case 1"; break;
case 2: message = "This is case 2"; break;
case 3: message = "This is case 3"; break;
case 4: message = "This is case 4"; break;
case 5: message = "This is case 5"; break;
case 6: message = "Done!"; break;
}
counter++;
}
res = "<message>" + message + "</message>";
PrintWriter ut = response.getWriter();
out.println("<response>");
out.println(res);
out.println("</response>");
out.close();
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
我们先来看dynamicUpdate.jsp里面的内容。点击"Launch"后,触发doStart()。首先把两个按钮屏蔽掉,然后将task=reset传给处理的servlet即DynamicUpdateServlet,并设置请求状态改变后,由startCallback函数处理。当send方法调用后,task参数以GET方法被传给DynamicUpdateServlet。在这个Servlet里面,有一个变量为counter,以后更新用的。里面的if语句先判断出task=reset,然后执行counter=1。虽然这里也写了<response>这些xml文件的内容,不过现在还没有用。那么,回到了第一个页面,由startCallback函数来处理。在这个函数里面,开始每隔2秒钟调用pollServer函数,并刷新计时器。
在pollServer函数里面,将task参数设置为foo(其实只要不设置为reset就可以),同时以GET方法传给DynamicUpdateServlet,之后由pollCallback函数处理。send方法被调用后,来看servlet。这个时候,task已经不是reset了,所以执行switch语句,此时counter=1,所以message="This is case 1"。然后在out.println里面写一个xml文件。接着就是重点的pollCallback函数了。
在这个函数里,请求处理完成后,首先通过xmlHttp.responseXML得到message内容,然后调用createRow函数来创建每一条被更新的内容,这些内容被放在<tr><td>标记里面。然后,得到该页面中显示动态更新的位置,这里是id为"dynamicUpdateArea"的table。然后查找到<tbody>中的<tr>,把每一条被更新的内容放到现有的<tr>前面一个位置。接着判断message的内容,如果message不为"Done!",则继续调用pollServer并刷新时间;否则结束更新,并恢复两个按钮。
当点击"Clear"按钮后,clearRows函数会先找到<tbody>的所有子节点,如果还有子节点就逐一去掉,以此来清除已经显示出来的内容。
这里面,更新的内容是一个简单的模拟。我想,实际应用中可以通过查找数据库来写入更新的内容。这个以后有待研究。
注意!有可能从这篇文章直接copy后执行会报错,因为博客输入可能会出现问题。只要稍微作修改即可,问题应该不是太大,应该能看懂并知道如何修改。例如,servlet中,PrintWriter ut其实是PrintWriter out。