首页 新闻 论坛 群组 Blog 文档 下载 读书 Tag 网摘 搜索 开源 FAQ 第二书店 博文视点 程序员
频道: 研发 数据库 中间件 信息化 视频 .NET Java 游戏 移动 服务: 人才 外包 培训
    图书品种:235680
       
热门搜索: ASP.NET Ajax Spring Hibernate Java

17.6  使用Ajax

了解了“Ajax是什么”、“Ajax能做什么”以及“在哪些地方使用Ajax”,相信读者都迫不及待地想知道如何使用Ajax。前面几节曾提过,Ajax不是一种新技术,而是几种成熟技术的组合,其中最为核心的是JavaScript脚本、实现异步通信的XMLHttpRequest对象(本书第16章)以及文档对象模型DOM(本书第5章及第15章)。在学习如何使用Ajax前,读者务必熟练掌握上述内容。本小节从简单的Ajax开发框架入手,逐步介绍Ajax在三种经典应用场景的使用,并配合实例讲解,其中包括:

— 数据验证——注册用户名唯一性验证实例;

— 按需读取数据——级联目录实例;

— 自动实时更新页面——自动实时刷新页面实例。

XMLHttpRequest对象是实现Ajax应用必不可少的核心技术,负责Ajax与服务器的异步交互,故Ajax应用实现的框架和异步通信的架构类似,也是围绕XMLHttpRequest对象的创建、发送请求、处理响应来展开的。

与前面章节介绍的客户端与服务器通信的框架类似,一个简单的Ajax框架一般包括三部分:XMLHttpRequest对象的创建、向服务器发送请求、处理服务器返回的数据并动态显示或者更新页面,下面分别予以详细论述。

 17.6.1  创建XMLHttpRequest对象

在本书前面的章节中已详细介绍了不同浏览器平台创建XMLHttpRequest对象的方法,其中也包括跨浏览器平台的智能HTTP请求,但其函数体均比较庞大,下面列举一种简单的创建方法,其代码如下所示:

function createXMLHTTP()

{

  var request;

  var browser = navigator.appName;

  //使用IE,则使用MSXML创建XMLHTTP对象

  if(browser == "Microsoft Internet Explorer")

  {

    var arrVersions = ["MSXML2.XMLHttp.5.0 ", "MSXML2.XMLHttp.4.0",

      "MSXML2.XMLHttp.3.0", "MSXML2.XMLHttp"," Microsoft.XMLHttp "];

    for(var i=0; i < arrVersions.length; i++)

    {

      try

      { 

       //从中找到一个支持的版本并建立XMLHTTP对象

        request = new ActiveXObject(arrVersions[i]);

        return request;

      }

      catch(exception)

      {

         //忽略,继续

      }

    }

  }

  //Mozilla等浏览器

  else

  {

    //否则返回一个XMLHttpRequest对象

    request = new XMLHttpRequest();

    return request;

  }

}

 17.6.2  向服务器发送请求

利用上面的创建函数创建XMLHTTP对象实例,向对应的服务器发送请求,可以是GET请求,也可以是POST请求,区别请参考第16章相关内容。本章为了简单起见,都以GET请求为例。简单的发送请求函数如下所示:

function Send_Request(url)

{

  //创建XMLHTTP对象实例

  var http_req=createXMLHTTP();

  //Open函数建立连接,一定是异步方式

  http.open("GET", url, true);

  //声明回调函数,也可以像第16章一样直接写在后面

  http_req.onreadystatechange = processRequest;

  //发送请求

  http_req.send(null);        

}

 17.6.3  处理服务器响应

在上一步声明的回调函数中,接收服务器返回的数据,并根据需求动态地更新页面(一般使用DOM协助完成)或者进行一些其他的操作(如弹出警告框等)。一个简单的处理函数如下所示:

function processRequest()      

{

  //4表示请求已完成

  if(http_req.readyState == 4)

  {

    if(http_req.status==200)

    {

      //获取服务段的响应文本

      var ResponseStr = http_req.responseText;

      //处理返回数据,这里只是把数据以警告框的方式显示

      alert(ResponseStr);

    }

    else

    {

      alert("请求页面异常!");

    }

  }

}

 17.6.4  完整的Ajax框架

综合创建XMLHttpRequest对象、向服务器发送请求和处理服务器响应三个步骤,得到完整的Ajax框架,代码如下所示:

<script language="JavaScript" type="text/javascript">

<!--

//全局对象实例

var http_req=false;

//创建函数

function createXMLHTTP()

{

  var request;

  var browser = navigator.appName;

  //使用IE,则使用MSXML 创建XMLHTTP对象

  if(browser=="Microsoft Internet Explorer")

  {

    var arrVersions = ["MSXML2.XMLHttp.5.0 ", "MSXML2.XMLHttp.4.0",

      "MSXML2.XMLHttp.3.0", "MSXML2.XMLHttp"," Microsoft.XMLHttp "];

    for (var i=0; i < arrVersions.length; i++)

    {

      try

      {

    //从中找到一个支持的版本并建立XMLHTTP对象

        request = new ActiveXObject(arrVersions[i]);

        return request;

      }

      catch (exception)

      {

         //忽略,继续

      }

    }

  }

  //Mozilla等浏览器

  else  

  {

    //否则返回一个XMLHttpRequest对象

    request = new XMLHttpRequest();

    return request;

  }  

}

//实例化XMLHTTP对象

http_req=createXMLHTTP();

//发送请求

function Send_Request(url)

{

  //创建XMLHttp对象实例

  //Open函数建立连接,一定是异步方式

  http.open("GET", url, true);

  //声明回调函数,也可以像第16章一样直接写在后面

  http_req.onreadystatechange = processRequest;

  //发送请求

  http_req.send(null);        

}

//处理函数

function processRequest()      

{

  //4表示请求已完成

  if(http_req.readyState == 4)

  {

    if(http_req.status==200)

    {

      //获取服务端的响应文本

      var ResponseStr = http_req.responseText;

      //处理返回数据,这里只是把数据以警告框的方式显示

      alert(ResponseStr);

    }

    else

    {

      alert("请求页面异常!");

    }

  }

}

-->

</script>

上面几个小节介绍了如何创建完整的Ajax框架,下面通过编写“Hello,Ajax”程序的实例来讲述Ajax程序的开发过程。

 17.6.5  开山之作:“Hello,Ajax”程序

类似于C++、Java等高级语言,下面以“Hello,Ajax”程序为例,简单介绍Ajax技术的应用方法,客户端页面对应的文档“HelloAjax.html”的代码如源程序17.1所示。

//源程序17.1

<!DOCTYPE HTML PUBLIC"-//W3C//DTD HTML 4.0//EN"

"http://www.w3.org/TR/REC-html140/strict.dtd">

<html>

<head>

<meta http-equiv="Content-Type" content="text/html; charset=gb2312">

<title>AJAX使用框架 ---- Hello,Ajax!</title>

<script language="JavaScript" type="text/javascript">

<!--

function createXMLHTTP()

{

  var request;

  var browser = navigator.appName;

  //若浏览器为IE,则使用XMLHTTP对象

  if(browser == "Microsoft Internet Explorer")

  {

    var arrVersions = ["Microsoft.XMLHttp", "MSXML2.XMLHttp.4.0",

      "MSXML2.XMLHttp.3.0", "MSXML2.XMLHttp","MSXML2.XMLHttp.5.0"];

    for (var i=0; i < arrVersions.length; i++)

    {

      try

      {

       //从中找到一个支持的版本并建立XMLHTTP对象

        request = new ActiveXObject(arrVersions[i]);

        return request;

      }

      catch(exception)

      {

        //忽略,继续

      }

    }

  }

  else

  {

    //否则返回一个XMLHttpRequest对象

    request = new XMLHttpRequest();

    return request;

  }

}

//全局XMLHttpRequest对象实例

var http = createXMLHTTP();

//发送请求函数

function HelloWorld()

{

  var username = document.forms[0].username.value;

  var url = "helloHandle.jsp?username="+escape(username);

  //指定服务端的地址

  http.open("GET", url, true);

  //声明回调函数

  http.onreadystatechange = getHello;

  //发送请求

  http.send(null);        

}

//回调函数,响应状态变化事件

function getHello()      

{

  // readyState=4表示请求已完成

  if (http.readyState == 4)

  {

    //获取服务端的响应文本

    var helloStr = http.responseText;

    //插入响应到ID为"ajax-ServerBack"的DIV标签内

    document.getElementById("ajax-ServerBack").innerHTML = helloStr;

  }

}

-->

</script>

</head>

<body >

<table with="50%">

  <tr>

    <td align='center'><h2>Hello,Ajax!</h2></td>

  </tr>

  <tr><td><hr></td></tr>

  <tr>

    <td>

      <form>

        Name:<input type="text" name="username" value="" >

      </form>

    </td>

  </tr>

  <tr>   

    <td align="center">

      <input type="button" name="" value="Say Hello to Ajax" onClick="HelloWorld()">

    </td>

  </tr>

  <tr>

    <td> 

      <div id="ajax-ServerBack" style="background:#ffffee;border:solid #cccccc"> </div>

    </td>

  </tr>

</table>

</body>

</html>

请求的服务器端页面(helloHandle.jsp)实现非常简单,只要取得请求参数,并以字符串的方式返回“Hello”信息即可,代码如源程序17.2所示。

//源程序17.2

<%@ page contentType="text/html; charset=gb2312" language="java" %>

<%

String username = request.getParameter("username");

String responseText="&nbsp;&nbsp;服务器返回:<br> Hello "+username+"! ----Ajax <br>";

out.print(responseText);

%>

把上述两页面放在JSP服务器的webapps\ajax目录下(JSP服务器的安装配置,请参考相关书籍),在浏览器的地址栏中输入:http://localhost:8080/ajax/HelloAjax.html,结果页面如图17.8所示。

在文本框中输入“Yang ShuiQing”,单击“Say Hello to Ajax”按钮,页面无须刷新,动态更新显示服务器返回的数据,其运行结果如图17.9所示。

                 

图17.8  Hello Ajax原始页面                        图17.9  Hello Ajax动态更新

 17.6.6  注册信息实时验证实例

利用Ajax来实时验证数据,是Ajax经典应用场景之一。在Web应用中,很多时候需要填写表单,而表单中的一些项需要验证,例如客户注册应用,要进行用户名的唯一性验证。传统的Web模式对数据验证方法有其不足,而Ajax很好地克服了这些缺点,提供了更好的用户体验。

下面来看一个完整的Ajax实现用户名唯一性验证的实例,主页面对应的文档“register.jsp”包含了Ajax应用的三个完整部分:XMLHttpRequest对象的创建、向服务器发送请求、处理服务器返回的数据并动态显示或者更新页面,其代码如源程序17.3所示。

//源程序17.3

<%@page language="java" contentType="text/html;charset=GBK"%>

<! DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN"

"http://www.w3.org/TR/REC-html140/strict.dtd">

<html>

<head>

<meta http-equiv="Content-Type" content="text/html; charset=gb2312">

<title>Ajax用户注册演示程序</title>

<script language="javascript" type="text/javascript">

<!--

//创建函数

function createXMLHTTP()

{

  var request;

  var browser = navigator.appName;

  //使用IE,则使用XMLHTTP对象

  if(browser == "Microsoft Internet Explorer")

  {

    var arrVersions = ["Microsoft.XMLHttp", "MSXML2.XMLHttp.4.0",

      "MSXML2.XMLHttp.3.0", "MSXML2.XMLHttp","MSXML2.XMLHttp.5.0"];

    for (var i=0; i < arrVersions.length; i++)

    {

      try

      {

       //从中找到一个支持的版本并建立XMLHTTP对象

        request = new ActiveXObject(arrVersions[i]);

        return request;

      }

      catch (exception)

      {

        //忽略,继续

      }

    }

  }

  else

  {

    //否则返回一个XMLHttpRequest对象

    request = new XMLHttpRequest();

    if(request.overrideMimeType)

    {

    request.overrideMimeType('text/xml');

   }

    return request;

  }

}

//全局XMLHTTP对象实例变量

var http = createXMLHTTP();

//发送请求

function chkUser()

{

  //请求"CheckUserName" ServLet

  var url = "CheckUserName";           

  var name = document.getElementById("userName").value;  

  url += ("?userName="+escape(name)+"&oprate=chkUser");

  http.open("GET",url,true);

  http.onreadystatechange = ProcessHttpResponse;

  http.send(null);

  return ;

}

//处理响应

function ProcessHttpResponse()

{

  if(http.readyState == 4)

  {

    if(http.status == 200)

    {

     var xmlDocument = http.responseXML;

     if(http.responseText!="该用户名有效,可以使用!")

      {

        //返回的信息动态显示

      document.getElementById("showStr").style.display = "";

      document.getElementById("userName").style.background= "#FF0000";

      document.getElementById("showStr").innerText = http.responseText;

     }

      else

      {

      document.getElementById("userName").style.background= "#FFFFFF";

      document.getElementById("showStr").style.display = "";

        document.getElementById("showStr").innerText = http.responseText;

     }

    }

    else

    {

    alert("你所请求的页面发生异常,可能会影响你浏览该页的信息!");

    alert(http.status);

    }

  }

}

//检验输入密码

function chkpassword()

{

  var m=document.form1;

  if(m.password.value.length>20 || m.password.value.length<6 )

  {

    document.getElementById("passwordStr").style.display = "";

   document.getElementById("password").style.background= "#FF0000";

   document.getElementById("passwordStr").innerText = "对不起,密码必须为英文字母、数字或下划线,长度为6~20!";

   }

   else

   {

    document.getElementById("password").style.background= "#FFFFFF";

    document.getElementById("passwordStr").style.display = "none";

   }

}

//验证两次密码是否一致

function chkconfirmPassword()

{

   var m=document.form1;

  if (m.password.value != m.confirmPassword.value)

  {

   document.getElementById("confirmPasswordStr").style.display = "";

   document.getElementById("confirmPassword").style.background= "#FF0000";

   document.getElementById("confirmPasswordStr").innerText = "对不起,密码与重复密码不一致!";

  }

  else

  {

   document.getElementById("confirmPassword").style.background= "#FFFFFF";

   document.getElementById("confirmPasswordStr").style.display = "none";

  }

}

//验证E-mail是否有效

function chkEmail()

{

   var m=document.form1;

   var email = m.email.value; 

  var regex = /^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+(\.[a-zA-Z0-9_-])+/;   

  var flag = regex.test(email);        

  if(!flag)   

  {

     document.getElementById("emailStr").style.display = "";

   document.getElementById("email").style.background= "#FF0000";

   document.getElementById("emailStr").innerText = "对不起,电子邮件地址无效!";

  }   

  else   

  {

     document.getElementById("email").style.background= "#FFFFFF";

   document.getElementById("emailStr").style.display = "none"; 

  }

}

//提交检查函数

function SubmitCheck()

{

  var m=document.form1;

  if(m.userName.value.length==0)

  {

   alert("对不起,用户名必须为英文字母、数字或下划线,长度为5~20。");

   m.userName.focus();

   return false;

  }

  if(m.password.value.length==0)

  {

   alert("对不起,密码必须为英文字母、数字或下划线,长度为5~20。");

   m.password.focus();

   return false;

  }

  if (m.password.value != m.confirmPassword.value)

  {

   alert("对不起,密码与重复密码不一致!");

   m.confirmPassword.focus();

   return false;

  }

  if(m.email.value.length==0)

  {

   alert("对不起,电子邮件地址不能为空!");

   m.email.focus();

   return false;

  }

  m.submit();

}

-->

</script>

<body>

<center>

<form name="form1" method="post" action="/Control?act=Register">

<h3 align="center">Ajax用户注册程序</h3>

<table align="center" width="500" border="1" >

  <tr>

    <td><font color="red">*</font></td>

    <td width="100">用户账号:</td>

    <td><input type="text" name="userName" maxlength="20"

              style="background=#FFFFFF" onBlur="chkUser()"></td>

    <td><div id="showStr" style="background-color:#FF9900;display:none"> </div> </td>

  </tr>

  <tr>

    <td><font color="red">*</font></td>

    <td>用户密码:</td>

    <td align="left"><input type="password" name="password" maxlength="22"

                        style="background=#FFFFFF" onBlur="chkpassword()"/> </td>

    <td><div id="passwordStr" style="background-color:#FF9900;display:none"> </div></td>

  </tr>

  <tr>

    <td><font color="red">*</font></td>

    <td>确认密码:</td> 

    <td><input type="password" name="confirmPassword" maxlength="20"

              style="background=#FFFFFF" onBlur="chkconfirmPassword()"/></td>

    <td><div id="confirmPasswordStr"

              style="background-color:#FF9900;display:none"></div></td>

  </tr>

  <tr>

    <td><font color="red">*</font></td>

    <td>Email:</td>

    <td><input type="text" name="email" maxlength="100" style="background= #FFFFFF"

              onBlur="chkEmail()"></td>

    <td><div id="emailStr" style="background-color:#FF9900;display:none"> </div></td>

  </tr>

</table>

<div align="center">

  <form>

   <input type="button" name="ok" value="确定 " onclick="SubmitCheck()">

   <input type="reset" name="reset" value="取消 ">

  </form>

</div>

</center>

</body>

</html>

从上面的请求函数可以看出,目标页面(register.jsp)请求“CheckUserName”,后者为服务器端的Servlet程序(CheckUserName.java),在其中声明了一个字符串列表来保存已经使用过的用户名,而GET请求响应函数获得请求的用户名参数,判断是否已存在并把判断结果返回客户端。服务器端文档“CheckUserName.java”的代码如源程序17.4所示。

//源程序17.4

package check;

import java.io.PrintWriter;

import java.io.IOException;

import javax.servlet.ServletConfig;

import javax.servlet.ServletException;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

public class CheckUserName extends HttpServlet

{

  private String msgStr="";

  //已注册名字列表

  public String[] usernameList;

  //响应GET请求函数

  protected void doGet(HttpServletRequest request,HttpServletResponse response) throws

  ServletException

  {

    String oprate=(String)request.getParameter("oprate");

    String userName=(String)request.getParameter("userName");

    try

    {

      if(oprate.equals("chkUser"))

      {

        response.setContentType("text/html;charset=GB2312");

        if(userName.length()<6||userName.length()>20)

        {

      msgStr="对不起,用户名必须为字母、数字或下划线,长度为6-20个字符!";

        }

        else

        {

          boolean bTmp=this.IsContain(userName); //查找数据库中有无该用户名

          if(bTmp)

            msgStr="对不起,此用户名已经存在,请更换用户名注册!";

          else

        msgStr="该用户名有效,可以使用!";

        }

        response.getWriter().write(msgStr);

      } 

    }//try

    catch(Exception ex){}

  }//doget

  //处理POST请求函数

  protected void doPost(HttpServletRequest request,HttpServletResponse response) throws   ServletException

  {

     doGet(request,response);

  }

  //Servlet初始函数

  public void init(ServletConfig config) throws ServletException

  {

    //初始已注册用户名字列表

    usernameList=new String []{"Tomny","yangshuiqing","huoguangcheng"};

  }

  //判断用户名是否已经存在

  private boolean IsContain(String param)

  {

    for (int i=0;i<usernameList.length ;i++ )

    {

       if(usernameList[i].equals(param))

       {

         return true;

       }

       else

         continue;

    }

    return false;

  }

} //End of Class

编译“CheckUserName.java”文件生成“CheckUserName.class”,将它放置于JSP服务器的webapps\ajax\WEB-INF\classes文件夹下,并修改WEB-INF\ajax\web.xml 文件(关于Servlet的配置,请参考相关书籍)。同时,将目标文件“register.jsp”放在JSP服务器下,使用浏览器载入http://local:8080/ajax/register.jsp,其结果如图17.10所示。

在“用户账号”对应的文本框中输入“yangshuiqing”,将输入焦点移离该文本框后,页面在不刷新的情况下与服务器异步交互,判断当前输入的用户名是否有效,并把判断的结果动态返回,如图17.11所示。

   

图17.10  Ajax注册原始页面                       图17.11  实时判断用户名无效

若在“用户账号”对应的文本框中输入“HelloAjax”,服务器判断为有效用户名,结果如图17.12所示。

同时,页面中也加入了对密码、E-mail地址的判断,在对应的文本框中输入相关信息后将输入焦点移出该文本框,均可得到判断结果,如图17.13所示。

   

图17.12  用户名有效                              图17.13  页面判断效果

 17.6.7  级联目录实例

按需读取数据是Ajax技术的最大特色。按需读取数据,减少数据冗余,大大降低了服务器的负担,同时也提高了带宽的利用率,对Web应用中的分类树或树型结构操作非常有效,使用Ajax实现级联目录成为一种趋势。

考察源程序17.5使用Ajax技术实现的级联目录的实例代码(tree.jsp):

//源程序17.5

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<html>

<head>

<title>Ajax级联测试程序.jsp</title>

<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">

<meta http-equiv="description" content="this is an Ajax Test page">

</head>

<script language="JavaScript" type="text/javascript">

<!--

//创建函数

function createXMLHTTP()

{

  var request;

  var browser = navigator.appName;

  if(browser == "Microsoft Internet Explorer")

  {

    var arrVersions = ["Microsoft.XMLHttp", "MSXML2.XMLHttp.4.0",

      "MSXML2.XMLHttp.3.0", "MSXML2.XMLHttp","MSXML2.XMLHttp.5.0"];

    for (var i=0; i < arrVersions.length; i++)

    {

      try

      {

       //从中找到一个支持的版本并建立XMLHTTP对象

        request = new ActiveXObject(arrVersions[i]);

        return request;

      }

      catch(exception)

      {

         //忽略,继续

      }

    }

  }

  else

  {

    //否则返回一个XMLHttpRequest对象

    request = new XMLHttpRequest();

    if(request.overrideMimeType)

    {

    request.overrideMimeType('text/xml');

   }

    return request;

  }

}

var req=createXMLHTTP();

//发送请求

function Send_Request(stateVal)

{

  var url = "SelectCity?state="+stateVal;

  if(req)

  {

    req.open("GET",url, true);

    req.onreadystatechange=processRequest;

    req.send(null);

  }

}

//处理响应

function processRequest()

{

  if(req.readyState == 4)

  {

    if(req.status == 200)

    {

      //XML DOM操作,取出city标记节点

      var city = req.responseXML.getElementsByTagName("city");

      var str=new Array();

      for(var i=0;i<city.length;i++)

      { 

       //把XML DOM节点的值读出

        str[i]=city[i].firstChild.data;

      }

      buildSelect(str,document.getElementById("city"));

    }

    else

    {

      alert("请求页面发生异常!");

    }   

  }

}

//动态添加级联选项

function buildSelect(str,sel)

{

  sel.options.length=0;

  for(var i=0;i<str.length;i++)

  {

    sel.options[sel.options.length]=new Option(str[i],str[i])

  }

}

-->

</script>

<body>

<h3>Ajax级联测试程序</h3><hr>

<form>

  <select name="state" onChange="Send_Request(this.value)">

    <option value="">省份</option>>

    <option value="hn">HUNAN</option>>

    <option value="gd">GUANGDONG</option>>

  </select>

  <select id="city">

    <option value="">城市</option>

  </select>

</form>

</body>

</html>

上述代码对应的主页面请求一个Servlet(SelectCity.java),后者判断客户端请求的是什么省份(一级目录),并把所选省份对应的城市(二级目录)以XML文档的方式发回客户端,其代码如源程序17.6所示。

//源程序17.6

package select;

import java.io.IOException;

import java.io.PrintWriter;

import javax.servlet.ServletException;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

public class SelectCity extends HttpServlet

{

  public SelectCity()

  {

    super();

  }

  public void destroy()

  {

    super.destroy();

  }

  //响应GET请求函数

  public void doGet(HttpServletRequest request, HttpServletResponse response)

      throws ServletException, IOException

  {

    response.setContentType("text/xml");

    response.setHeader("Cache-Control", "no-cache");

    String state = request.getParameter("state");

    StringBuffer sb=new StringBuffer("<state>");

    if ("hn".equals(state))

    {

      sb.append("<city>changsha</city><city>xiangtan</city><city>zhuzhou </city>");

    }

    else if("gd".equals(state))

    {

      sb.append("<city>guangzhou</city><city>shaoguan</city><city>zhanjiang </city>");

    }

    sb.append("</state>");

    PrintWriter out=response.getWriter();

    out.write(sb.toString());

    out.close();

  }

}

按照第17.6.6节“注册信息实时验证实例”中讲述的方法,将服务器端响应文件“SelectCity.java”编译为“SelectCity.class”并配置JSP服务器,使用浏览器载入http://localhost:8080/tree.jsp,其结果如图17.14所示:

选择一级目录“HUNAN”,则对应的二级目录:“changsha、xiangtan、zhuzhou”等城市作为选项在第二个下拉框中显示,如图17.15所示。

               

图17.14  级联目录实例                图17.15  一级目录HUNAN对应的二级目录

如选择一级目录“GUANGDONG”,则对应的二级目录:“guangzhou、shaoguan、zhanjiang”等城市作为选项在第二个下拉框中出现,如图17.16所示。

图17.16  一级目录GUANGDONG对应的二级目录

在该实例中,每次交互都只是读取对应的二级目录,按用户的需要读取数据,大大减少数据冗余,提高带宽利用率。该实例交互数据量较小,比较还不是很明显,如果交互数据量很庞大时,Ajax性能的提高是非常显著的。这也是Ajax受到追捧的原因之一。

 17.6.8  自动实时更新页面

在信息千变万化的当今时代,Web应用的数据变化也是十分迅速的,例如新闻信息、天气预报、实时的聊天内容还有现在比较火的股市动态等。而在传统的Web应用中,用户为了得到相关新的内容,不得不反复刷新页面,或者页面实现定时刷新。刷新意味着装载页面,不但要载入更新的内容,原本已经加载的旧内容也要加载一遍,浪费带宽的同时,用户等待时间也相对较长。而在实时动态更新页面方面,Ajax有着得天独厚的优势,因此自动更新页面也是Ajax的经典应用之一。

在下面的实例中用户无须不停地刷新页面,页面会每隔一分钟和服务器自动交互一次,获得服务器系统时间,并动态更新数据到客户端页面。文档“newTime.jsp”的代码如源程序17.7所示。

//源程序17.7

<!DOCTYPE HTML PUBLIC”-//W3C//DTD HTML 4.0//EN”

"http://www.w3.org/TR/REC-html140/strict.dtd">

<html>

<head>

<meta http-equiv="Content-Type" content="text/html; charset=gb2312">

<title>Ajax定时刷新页面实例!</title>

</head>

<script language="JavaScript" type="text/javascript">

<!--

//创建函数

function createXMLHTTP()

{

  var request;

  var browser = navigator.appName;

  //使用IE,则使用XMLHTTP对象

  if(browser == "Microsoft Internet Explorer")

  {

    var arrVersions = ["Microsoft.XMLHttp", "MSXML2.XMLHttp.4.0",

      "MSXML2.XMLHttp.3.0", "MSXML2.XMLHttp","MSXML2.XMLHttp.5.0"];

    for (var i=0; i < arrVersions.length; i++)

    {

      try

      {

       //从中找到一个支持的版本并建立XMLHTTP对象

        request = new ActiveXObject(arrVersions[i]);

        return request;

      }

      catch (exception)

      {

         //忽略,继续

      }

    }

  }

  else

  {

    //否则返回一个XMLHttpRequest对象

    request = new XMLHttpRequest();

    if(request.overrideMimeType)

    {

    request.overrideMimeType('text/xml');

   }

    return request;

  }  

}

var http_request = createXMLHTTP();

//请求函数

function makeRequest(url)

{

  http_request.open('GET', url, true);

  http_request.onreadystatechange = processRequest;

  //禁止IE缓存

  http_request.setRequestHeader("If-Modified-Since","0");

  //发送数据

  http_request.send(null);

  //每60秒刷新一次页面

  setTimeout("makeRequest('"+url+"')", 60000);

}

//处理响应

function processRequest()

{

  if(http_request.readyState == 4)

  {

    if(http_request.status == 0 || http_request.status == 200)

    {

      var result = http_request.responseText;

      if(result=="")

      {

        result = "系统时间获取失败";

      }

      document.getElementById ("sysTimeShow").innerHTML="系统时间:"+result;

    }

    //http_request.status != 200

    else

    {

      alert("请求失败!");

    }

  }

}

-->

</script>

<body onload="makeRequest('getSystemTime.jsp')">

<center>

<form name="dateForm">

<table>

  <tr>

    <td align="center"><h2>一分钟刷新一次</h2></td>

  </tr>

  <tr>

    <td><hr></td>

  </tr>

  <tr>

    <td colspan="2" align="center"><div id="sysTimeShow"></div> </td>

  </tr>

</table>

</form>

</center>

</body>

</html>

服务器端页面“getSystemTime.jsp”用于获得当前系统时间,其代码如源程序17.8所示。

//源程序17.8

<%@ page language="java"%>

<%@ page contentType="text/html;charset=GB2312" %>

<%@ page import="java.util.Date"%>

<%@ page import="java.sql.Timestamp"%>

<%@ page import="java.io.IOException"%>

<%

  Date d = new Date();

  Timestamp ts = new Timestamp(d.getTime());

  String result = ts.toString().substring(0,16);

  out.write(result,0,result.length());

%>

把上述两个文件放置在JSP服务器的webapps目录下,使用浏览器载入后,结果页面如图17.17所示。

间隔一分钟后,无须手动刷新,页面自动更新,如图17.18所示。

                 

图17.17  Ajax自动更新实例                       图17.18  间隔一分钟自动更新

使用Ajax自动更新内容,无须重载整个页面,只需动态地更新在服务器端已被更新的内容,在加快更新速度的同时,页面更新过程在用户不知不觉的情况下进行,其间用户可以进行其他操作,提供了很好的用户体验。

 17.6.9  小结

本节从Ajax的简单框架入手,并配合一个简单的“Hello,Ajax”程序,介绍了Ajax程序的架构,带领读者进入Ajax之门;同时,本节通过三个经典的Ajax实例程序详细介绍了Ajax在三种经典场景的应用,通过实例说话,帮助读者基本掌握Ajax开发技术。

注意:本节中所有测试实例都在JDK 1.5.0与Tomcat 5.0中调试通过,浏览器中输入的地址,如http://localhost:8080/tree.jsp,都是基于程序是放在Tomcat服务器webapps目录下的。如果读者使用不同的环境,或者建立不同的文件夹,配置或者路径均需要做相应的改变。

查看所有评论(0)条】

最近评论



正在载入评论列表...
热点评论