AJAX构建应用程序

IBM develope上提供了一个AJAX实现应用程序,整理一下.

AJAX 支持动态、异步的 Web 体验,不需要页面刷新。它集成了以下技术:

  • XHTML CSS 提供了基于标准的表示。
  • 文档对象模型(DOM)提供了动态显示和交互。
  • XML XSLT 提供了数据交换和操纵。
  • XMLHttpRequest 提供了异步数据检索。
  • JavaScript 把每一样东西绑定在一起。

   使用 XMLHttpRequest,可以用 JavaScript 发出到服务器的请求,并在不阻塞用户的情况下处理响应。在创建 Web 站点并用 XMLHttpRequest 在客户机浏览器上无刷新地执行屏幕更新的同时,它还提供了更多灵活性和丰富的用户体验。
   下面介绍一个例子。运行需要tomcat作为服务器,这里是代码的下载:/Files/JeffChen/ajax.rar(汗,不支持.war格式的文件,把源码压缩成RAR了,下载下来解压后放到tomcat web程序部署目录就可以)。我已经测试过了。下面是源码的具体解释,适合新手入门.
    

 

    应用程序是一个使用 Java 服务器页面(JSP)技术开发的单一 Web 页面。用户可以用 Web 浏览器调用 Web 页面并输入应用程序要实时验证的订购 ID。在 ID 异步验证的时候,用户可以输入更多信息。用户可以根据作者出版者 查看图书的书名。屏幕会根据用户的选择填充作者列表出版者列表。根据选择,书名列表 会被填充。所有这些列表都是实时填充的 —— 换句话说,页面没有刷新,但是数据仍然来自后台层。我们把这种现象叫做实时刷新
    从 上图可以看出,XMLHttpRequest JavaScript 对象帮助进行实时异步处理。该对象采用 XML 格式通过 HTTP 对位于 Web 容器内的 LibraryServlet 发出请求。然后 servlet 查询数据库、提取数据并发送回客户机,还是采用 XML 格式通过 HTTP 进行传送。请求和响应都是在没有刷新页面的情况下实时发生的。

   我们研究示例图书订购应用程序的代码,并进一步查看每个基于 AJAX Javascript 组件:

  • 验证订购 ID
  • 查看作者
  • 查看出版者
  • 查看书名

先从验证订购 ID 的函数 <input type="text" name="subscriptionID" οnblur="validate(this.form)"/> 开始。这个代码生成文本字段,用户可以在里面输入订购 ID。用户输入 ID 并移到表单的下一个字段时,触发 onBlur 事件。这个事件调用 JavaScript 函数 validate()

None.gif var  req;
ExpandedBlockStart.gifContractedBlock.gif
function  validate(formObj)  dot.gif {
InBlock.gif    init();
InBlock.gif    req.onreadystatechange 
= subscriptionValidator;
InBlock.gif    req.send(
"subscriptionID=" + formObj.subscriptionID.value);
ExpandedBlockEnd.gif}

None.gif

validate() 函数接受 formObj 作为参数。它首先调用 init() 函数:

ExpandedBlockStart.gif ContractedBlock.gif function  init()  dot.gif {
ExpandedSubBlockStart.gifContractedSubBlock.gif    
if (window.XMLHttpRequest) dot.gif{
InBlock.gif        req 
= new XMLHttpRequest();
ExpandedSubBlockStart.gifContractedSubBlock.gif    }
 else if (window.ActiveXObject) dot.gif{
InBlock.gif        req 
= new ActiveXObject("Microsoft.XMLHTTP");
ExpandedSubBlockEnd.gif    }

InBlock.gif    
var url = "/Library/LibraryServlet";
InBlock.gif    req.open(
"POST", url, true);
InBlock.gif    req.setRequestHeader(
"Content-Type""application/x-www-form-urlencoded");
ExpandedBlockEnd.gif}

None.gif

查看代码: init()

现在看 init() 函数的工作(我们把代码分成几部分):

ExpandedBlockStart.gifContractedBlock.gifif (window.XMLHttpRequest) dot.gif {
InBlock.gif    req 
= new
 XMLHttpRequest();
ExpandedBlockStart.gifContractedBlock.gif}
 else if (window.ActiveXObject) dot.gif {
InBlock.gif    req 
= new ActiveXObject("Microsoft.XMLHTTP"
);
ExpandedBlockEnd.gif}

None.gif

init() 函数首先创建 XMLHttpRequest 对象。这个请求对象是 AJAX 的核心。它以 XML 格式发送和接收请求。这段代码检查浏览器对 XMLHttpRequest 对象的支持(多数浏览器都支持它)。如果使用 Microsoft Internet Explorer 5.0 以上版本,那么就执行第二个条件。

None.gif req.open( " POST " , url,  true );
None.gifreq.setRequestHeader(
" Content-Type " " application/x-www-form-urlencoded " );
None.gif

代码创建了 XMLHttpRequest 对象之后,需要设置某些请求属性。在前面的代码中,第一行设置请求方法、请求 URL 和请求的类型(是否异步)。它通过调用 XMLHttpRequest 对象上的 open() 方法做这件事。

这里我们要使用 POST 方法。理想情况下,当需要在服务器上修改状态时,请使用 POST。我们的应用程序并不修改状态,但我们仍然倾向于使用 POSTurl 是要执行的 servlet URLtrue 表明我们要异步地执行请求。

对于 POST 方法,我们需要设置 Content-Type 这个请求头。对于 GET 方法来说不需要这个设置。

None.gif
ExpandedBlockStart.gifContractedBlock.gif
function  validate(formObj)  dot.gif {
InBlock.gif    init();
InBlock.gif    req.onreadystatechange 
= subscriptionValidator;
InBlock.gif    req.send(
"subscriptionID=" + formObj.subscriptionID.value);
ExpandedBlockEnd.gif}

None.gif

查看代码:回调句柄 1

继续查看验证方法,下面把 subscriptionValidator 回调句柄分配给 onreadystatechange,请求状态的每个变化都会触发它。

这个回调句柄 都负责什么呢?因为正在异步地处理请求,所以需要一个回调句俩,从服务器返回完整响应的时候调用它 —— 回调句柄是对订购 ID 进行验证的地方(也就是编写实际的验证代码的地方)。

句柄充当侦听器。它一直等待响应完成。为了发送请求,最后一行调用了 send() 方法。请求以名称= 对的形式发送。对于 GET 方法,请求作为 URL 的一部分发送,所以 send() 方法被传递了一个空参数。

请求被发送到 servletservlet 处理请求并实时地发回响应。这就是 servlet 处理请求的方式。下一个代码段表示了 LibraryServlet doPost() 方法。

None.gif
None.gifpublic 
void  doPost(HttpServletRequest req, HttpServletResponse resp) throws 
ExpandedBlockStart.gifContractedBlock.gifServletException, IOException 
dot.gif {
InBlock.gif    String ID 
= null;
InBlock.gif    ID 
= req.getParameter("subscriptionID");
ExpandedSubBlockStart.gifContractedSubBlock.gif    
if (ID != nulldot.gif{
InBlock.gif        String status 
= "<message>" + this.validID(ID) + "</message>";
InBlock.gif    
this.writeResponse(resp, status);
ExpandedSubBlockEnd.gif    }

ExpandedBlockEnd.gif}

None.gif

查看代码:回调句柄 2

doPost() 方法从请求参数得到 subscriptionID。为了验证 ID,它调用 validID() 方法。这个方法验证 ID,如果 ID 正确,则返回 true,否则返回 false。它用 XML 格式构造返回状态,并调用 writeResponse() 方法来写响应。现在来看 writeResponse() 方法。

ExpandedBlockStart.gif ContractedBlock.gif public  void  writeResponse(HttpServletResponse resp, String output) throws IOException  dot.gif {
InBlock.gif    resp.setContentType(
"text/xml");
InBlock.gif    resp.setHeader(
"Cache-Control""no-cache");
InBlock.gif    resp.getWriter().write(output);
ExpandedBlockEnd.gif}

None.gif

响应用 XML 格式发送。第一行设置响应的内容类型为 text/xml。第二行把头 Cache-Control 的值设为 no-cache。这个值是必需的。AJAX 要求响应的输出不能被浏览器缓存。最后一行调用 getWriter().write() 方法来写响应。

查看代码:回调句柄 3

请求由 servlet 处理,响应被发送回客户机。请记住,所有这些都在后台发生,没有页面刷新。现在 前面 讨论过的回调句柄方法会处理并解析响应:

ExpandedBlockStart.gif ContractedBlock.gif function  subscriptionValidator()  dot.gif {
ExpandedSubBlockStart.gifContractedSubBlock.gif    
if (req.readystate == 4dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif    
if (req.status == 200dot.gif{
InBlock.gif        
var messageObj = req.responseXML.getElementsByTagName("message")[0];
InBlock.gif        
var message = messageObj.childNodes[0].nodeValue;
ExpandedSubBlockStart.gifContractedSubBlock.gif        
if (message == "true"dot.gif{
InBlock.gif        msg.innerHTML 
= "Subscription is valid";
InBlock.gif        document.forms[
0].order.disabled = false;
ExpandedSubBlockStart.gifContractedSubBlock.gif        }
 else dot.gif{
InBlock.gif        msg.innerHTML 
= "Subscription not valid";
InBlock.gif        document.forms[
0].order.disabled = true;
ExpandedSubBlockEnd.gif        }

ExpandedSubBlockEnd.gif    }

ExpandedSubBlockEnd.gif    }

ExpandedBlockEnd.gif}

None.gif

查看代码:回到 XMLHttpRequest

如前所述,XMLHttpRequest 对象是构造和发送请求的核心对象。它也负责读取和解析从服务器返回的响应。请看下面几部分代码。

ExpandedBlockStart.gif ContractedBlock.gif if  (req.readystate  ==   4 dot.gif {
ExpandedSubBlockStart.gifContractedSubBlock.gif    
if (req.status == 200dot.gif{
InBlock.gif

前面的代码检查请求的状态。如果请求处在就绪状态,就读取和解析响应。

就绪状态是什么意思呢?当请求对象的属性 readystate 的值是 4 时,就意味着客户机接收到了响应而且接收完成。下面我们检查请求的状态(响应是正常页面还是错误页面)。为了保证响应正常,要检查状态的值是否为 200。如果 status 的值是 200,就会处理响应。

None.gif var  messageObj  =  req.responseXML.getElementsByTagName( " message " )[ 0 ];
None.gif
var  message  =  messageObj.childNodes[ 0 ].nodeValue;
ExpandedBlockStart.gifContractedBlock.gif
if  (message  ==   " true " dot.gif {
InBlock.gif    msg.innerHTML 
= "Subscription is valid";
InBlock.gif    document.forms[
0].order.disabled = false;
ExpandedBlockStart.gifContractedBlock.gif}
  else   dot.gif {
InBlock.gif    msg.innerHTML 
= "Subscription not valid";
InBlock.gif    document.forms[
0].order.disabled = true;
ExpandedBlockEnd.gif}
    }
None.gif

接下来,请求对象通过调用 responseXML 属性读取响应。请注意 servlet XML 格式发送回响应,所以我们使用 responseXML。如果响应是以文本格式发送的,那么可以使用 responseText 属性。

在这个示例中,我们处理 XMLservlet 把响应构建在一个 <message> 标记中。要解析这个 XML 标记,请在 XMLHttpRequest 对象的 responseXML 属性上调用 getElementsByTagName() 方法。它得到标记的名称以及标记的子值。根据解析到的值,格式化响应并用 HTML 改写。

现在就完成了对订购 ID 的验证,没有页面刷新。

查看代码:查看作者、出版者和书名

其他的功能 —— 查看作者查看出版者 查看书名 —— 工作的方式类似。只是需要为每个功能定义独立的句柄:

ExpandedBlockStart.gif ContractedBlock.gif function  displayList(field)  dot.gif {
InBlock.gif    init();
InBlock.gif    titles.innerHTML 
= " ";
InBlock.gif    req.onreadystatechange 
= listHandler;
InBlock.gif    req.send(
"select=" + escape(field));
ExpandedBlockEnd.gif}

None.gif
ExpandedBlockStart.gifContractedBlock.gif
function  displayTitles(formObj)  dot.gif {
InBlock.gif    init();
InBlock.gif    
var index = formObj.list.selectedIndex;
InBlock.gif    
var val = formObj.list.options[index].value;
InBlock.gif    req.onreadystatechange 
= titlesHandler;
InBlock.gif    req.send(
"list=" + val);
ExpandedBlockEnd.gif}

None.gif

请记住,示例应用程序允许用户根据作者和出版者查看书名。所以显示的或者是作者列表 或者是出版者列表。在这类场景中,应用程序只能根据用户的选择调用一个回调句柄 —— 换句话说,对于作者和出版者列表,只有一个 listHandler 回调句柄。

显示书名列表需要使用 titlesHandler。其余的功能仍然一样:servlet 处理请求,用 XML 格式写回响应。然后读取、解析、格式化响应,用 HTML 改写。可以用 HTML 把列表呈现为 select......options 标记。这个示例代码段显示了 titlesHandler 方法。

None.gif var  temp  =   " <select name=\ " titles\ "  multiple\> " ;
ExpandedBlockStart.gifContractedBlock.gif
for  ( var  i = 0 ; i < index; i ++ dot.gif {
InBlock.gif    
var listObj = req.responseXML.getElementsByTagName("list")[i];
InBlock.gif    temp 
= temp + "<option value=" + i +">" + listObj.childNodes[0].nodeValue 
InBlock.gif
+ "</option>";
ExpandedBlockEnd.gif}

None.giftemp 
=  temp  +   " </select> " ;
None.giftitles.innerHTML 
=  temp;
None.gif













评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值