在本文中将给出一个例子来介绍使用AJAX
技术从服务端获得数据的三种方法。这个例子很简单,就是两个选择框(html
中的
方法一、从服务端获得XML
格式的数据
从服务端获得数据的最容易想到的方法就是在服务端反加一定格式的数据,一般是XML
格式,然后在服务端使用XMLDocument
或其他技术来读取这些数据,并生成
//
select表示
function addOptions(select, xml)
{
if (select)
{
var options = "" ;
for ( var i = 0 ; i < xml.childNodes[ 0 ].childNodes.length ; i ++ )
{
if (xml.childNodes[ 0 ].childNodes[i].nodeName == " list " )
{
var s = "" ;
if (isIE())
s = xml.childNodes[ 0 ].childNodes[i].text;
else
s = xml.childNodes[ 0 ].childNodes[i].textContent
options += "
"
+
s
+
"
'>
"
;
options += s;
options += "
"
}
}
var id = select.id;
if (isIE())
select.outerHTML = " " ;
else
select.innerHTML = options;
}
}
function addOptions(select, xml)
{
if (select)
{
var options = "" ;
for ( var i = 0 ; i < xml.childNodes[ 0 ].childNodes.length ; i ++ )
{
if (xml.childNodes[ 0 ].childNodes[i].nodeName == " list " )
{
var s = "" ;
if (isIE())
s = xml.childNodes[ 0 ].childNodes[i].text;
else
s = xml.childNodes[ 0 ].childNodes[i].textContent
options += "
options += s;
options += "
}
}
var id = select.id;
if (isIE())
select.outerHTML = " " ;
else
select.innerHTML = options;
}
}
onReadState
函数将在XMLHttpRequest
对象的异步访问服务端时调用。当readyState
为4
时表示成功从服务端返回XML
数据。这个函数的实现代码如下:
//
myRequest表示XMLHttpRequest对象,selectId表示
function onReadyState(myRequest, selectId)
{
if (myRequest.readyState == 4 ) // 4表示成功获得相应信息
{
try
{
var xml = myRequest.responseXML; // 获得XMLDocument对象
var kind = document.getElementById(selectId); // 获得
addOptions(kind, xml); // 向
}
catch (e)
{
alert( " onReadyState: " + e);
}
}
}
function onReadyState(myRequest, selectId)
{
if (myRequest.readyState == 4 ) // 4表示成功获得相应信息
{
try
{
var xml = myRequest.responseXML; // 获得XMLDocument对象
var kind = document.getElementById(selectId); // 获得
addOptions(kind, xml); // 向
}
catch (e)
{
alert( " onReadyState: " + e);
}
}
}
getData
函数负责向服务端发送请求,并设置异步事件。实现代码如下:
function
getData(url, selectId)
{
var myRequest = getXMLHTTPRequest(); // 获得一个XMLHttpRequest对象
if (myRequest)
{
myRequest.onreadystatechange = function () // 接收获得数据状态的事件函数
{
onReadyState(myRequest, selectId);
}
try
{
myRequest.open( " post " , url, true );
}
catch (e)
{
alert(e);
}
try
{
myRequest.send( "" );
}
catch (e)
{
alert(e);
}
}
}
{
var myRequest = getXMLHTTPRequest(); // 获得一个XMLHttpRequest对象
if (myRequest)
{
myRequest.onreadystatechange = function () // 接收获得数据状态的事件函数
{
onReadyState(myRequest, selectId);
}
try
{
myRequest.open( " post " , url, true );
}
catch (e)
{
alert(e);
}
try
{
myRequest.send( "" );
}
catch (e)
{
alert(e);
}
}
}
现在本例子的核心代码已经实现完成,下一步就是在html
而加载时从服务端获得第1
个
DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
>
< html >
< head >
< title > title >
< meta http-equiv ="Content-Type" content ="text/html; charset=UTF-8" >
< script type ="text/javascript" src ="myscript.js" >
script >
head >
< body >
< select id ="bigKind" onchange ="onChange(this)" >
select >
< select id ="smallKind" >
select >
body >
html >
< html >
< head >
< title > title >
< meta http-equiv ="Content-Type" content ="text/html; charset=UTF-8" >
< script type ="text/javascript" src ="myscript.js" >
script >
head >
< body >
< select id ="bigKind" onchange ="onChange(this)" >
select >
< select id ="smallKind" >
select >
body >
html >
从上面代码可以看出,这两个
window.onload
=
onLoad
function onLoad()
{
try
{
getData( " ../GetXML " , " bigKind " );
}
catch (e)
{
alert( " onLoad: " + e);
}
}
function onLoad()
{
try
{
getData( " ../GetXML " , " bigKind " );
}
catch (e)
{
alert( " onLoad: " + e);
}
}
其中 GetXML 是一个 Servlet 程序(读者可以将其换成其他的服务端程序,如 asp.net 、 php 的)。下面是这个 GetXML 程序的实现代码:
package
servlet;
import java.io. * ;
import javax.servlet. * ;
import javax.servlet.http. * ;
import database.MyData;
public class GetXML extends HttpServlet
{
protected void proce***equest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
response.setContentType( " application/xml;charset=UTF-8 " );
PrintWriter out = response.getWriter();
try
{
String s = request.getParameter( " kind " );
out.println( " " );
if (s == null )
{
for (String key : MyData.data.keySet())
{
out.println( "
}
} else
{
s = java.net.URLDecoder.decode(s, " UTF-8 " );
System.out.println(s);
java.util.List < String > smallKind = MyData.data.get(s);
if (smallKind != null )
{
for (String kind : smallKind)
{
out.println( "
}
}
}
out.println( " " );
} finally
{
out.close();
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
proce***equest(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
proce***equest(request, response);
}
public String getServletInfo()
{
return " Short description " ;
}
}
import java.io. * ;
import javax.servlet. * ;
import javax.servlet.http. * ;
import database.MyData;
public class GetXML extends HttpServlet
{
protected void proce***equest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
response.setContentType( " application/xml;charset=UTF-8 " );
PrintWriter out = response.getWriter();
try
{
String s = request.getParameter( " kind " );
out.println( " " );
if (s == null )
{
for (String key : MyData.data.keySet())
{
out.println( "
}
} else
{
s = java.net.URLDecoder.decode(s, " UTF-8 " );
System.out.println(s);
java.util.List < String > smallKind = MyData.data.get(s);
if (smallKind != null )
{
for (String kind : smallKind)
{
out.println( "
}
}
}
out.println( " " );
} finally
{
out.close();
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
proce***equest(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
proce***equest(request, response);
}
public String getServletInfo()
{
return " Short description " ;
}
}
不管读者会不会java
和servlet
,从这个程序中的proce***equest
方法中都可以看出,首先会获得请求参数kind
,如果这个参数不存在,则返回bigKind
所需要的数据,以xml
格式返回,类似于如下的格式:
<
data
>
< list > data1 list >
< list > data2 list >
data >
< list > data1 list >
< list > data2 list >
data >
如果 kind 参数存在,则在 MyData.data 中查询第 2 个
package
database;
import java.util. * ;
public class MyData {
public static Map < String, List < String >> data;
static {
data = new HashMap < String, List < String >> ();
List < String > eProducts = new LinkedList < String > ();
eProducts.add( " 手机 " );
eProducts.add( " 数码/IT " );
eProducts.add( " 家电 " );
eProducts.add( " 电脑 " );
data.put( " 消费电子 " , eProducts);
List < String > goods = new LinkedList < String > ();
goods.add( " 化妆 " );
goods.add( " 健康 " );
goods.add( " 玩具 " );
goods.add( " 办公/文体 " );
goods.add( " 童装童鞋 " );
goods.add( " 其他 " );
data.put( " 日用百货 " , goods);
List < String > books = new LinkedList < String > ();
books.add( " 小说 " );
books.add( " 动漫 " );
books.add( " 经济 " );
books.add( " 法律 " );
books.add( " 计算机 " );
books.add( " 英语 " );
books.add( " 通讯 " );
books.add( " 其他 " );
data.put( " 图书 " , books) ;
}
}
import java.util. * ;
public class MyData {
public static Map < String, List < String >> data;
static {
data = new HashMap < String, List < String >> ();
List < String > eProducts = new LinkedList < String > ();
eProducts.add( " 手机 " );
eProducts.add( " 数码/IT " );
eProducts.add( " 家电 " );
eProducts.add( " 电脑 " );
data.put( " 消费电子 " , eProducts);
List < String > goods = new LinkedList < String > ();
goods.add( " 化妆 " );
goods.add( " 健康 " );
goods.add( " 玩具 " );
goods.add( " 办公/文体 " );
goods.add( " 童装童鞋 " );
goods.add( " 其他 " );
data.put( " 日用百货 " , goods);
List < String > books = new LinkedList < String > ();
books.add( " 小说 " );
books.add( " 动漫 " );
books.add( " 经济 " );
books.add( " 法律 " );
books.add( " 计算机 " );
books.add( " 英语 " );
books.add( " 通讯 " );
books.add( " 其他 " );
data.put( " 图书 " , books) ;
}
}
其中 data 变量中的 key 值就是 bigKind 中的值,而每一个 key 对应的值(一个 List
function
onChange(obj)
{
try
{
getData(encodeURI(encodeURI( " ../GetXML?kind= " + obj.options[obj.selectedIndex].value)), " smallKind " );
}
catch (e)
{
alert(e);
}
}
{
try
{
getData(encodeURI(encodeURI( " ../GetXML?kind= " + obj.options[obj.selectedIndex].value)), " smallKind " );
}
catch (e)
{
alert(e);
}
}
这个函数是
标签的onchange
事件函数。obj
表示
标签本身。这个函数中只有一条有实际意义的语句,也就是调用了getData
方法,这个方法人在onLoad
方法中调用getData
时差不多,只是在传送url
时使用了两个encodeURI
方法。由于XMLHttpRequest
方法以utf-8
向服务端发送数据,因此,要使用两个encodeURI
向服务端发送%xx
形式的utf-8
编码,然后在服务端进行解析。我们在GetXML
中的proce***equest
方法中可以找到如下的一条语句:
s
=
java.net.URLDecoder.decode(s,
"
UTF-8
"
);
就是进行解码操作。
注:如果在
IE
中,客户端可以不使用
encodeURI
对带中文的
URL
进行编码,服务端也不用解码。在服务端仍然可以正常显示中文。但在
firefox
中就必须要进行编码和解码。因此,要想跨浏览器,就需要使用本文所述的方法。
方法二、直接获得...
内容的字符串
上面的获得数据的方法是从服务端获得了一个XML
文档,并转换成XMLDocument
对象,然后解析。这种方法虽然很好,但是操作XMLDocument
对象还是有些麻烦,因此,我们可以在服务端直接反回
标签所需要的
标签字符串,然后将这些字符串传给
对象的innerHTML
或outerHTML
就可以了。服务端的代码和上面的实现代码类似,只需要将
去掉,然后将
-
改为
response.setContentType("text/html;charset=UTF-8");
客户端可通过XMLHttpRequest
对象的responseText
属性获得这些含有
的文本,并将其赋给innerHTML
或outerHTML
属性。这种方法虽然很方便,但并不灵活。如果客户端不使用
标签,而是使用
或其他的标签显示数据,那么返回的这些数据就没什么用处了。而即方便,又灵活的应该是下面要介绍的方法。