反向Ajax的基本概念是客户端不必从服务器获取信息,服务器会把相关信息直接推送到客户端。这样做的目的是解决Ajax传统Web模型所带来的一个限制:实时信息很难从技术上解决。原因是,客户端必须联系服务器,主动询问是否存在变更,如果有变更就会更新页面(或者页面的一部分)。虽然可以非常快速完成这个操作,让人感觉好像是实时的,但是实际上不是实时的。我们需要的是,服务器联系查看其页面的所有浏览器,并通告所发生的变更。
反向Ajax是克服这个限制的一种方式。像Ajax本身一样,这不是一门专门的技术,而是按照不寻常方式组合使用已有的技术达到不寻常的效果。
传统的Web模式(也就是非Ajax的应用程序)有一系列鲜明的事件。简单来说,用户在客户端的一个动作会导致向服务器发出一个请求,然后服务器按照请求进行相应处理,并把处理结果作为响应传回客户端,这个响应通常是一个完整的新的UI视图。这种处理过程反复循环,直到用户决定离开当前Web站点。在基于Ajax的应用程序的事件序列中,某个用户动作会导致对某个客户端Ajax引擎的调用,不论它是JavaScript代码,还是其他库。这个引擎会向服务器发出一个请求,服务器按照非Ajax模式进行处理,然后返回响应。响应内容首先被Ajax引擎处理,然后调用某些客户端代码以更新页面。同样,这个循环会无止境进行,直到用户离开当前页面。
现在总共有三种DWR支持的技术可以辅助完成这种技术,其中两种技术都属于"主动的"反向Ajax,第三种被认为是"被动的"反向Ajax。下面我主要介绍一下实现第三种(PiggyBack)的过程。
第一步,配置好DWR(引入dwr.jar)
第二步:创建web.xml,代码如下:
<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"> <!-- 配置DWR的核心Servlet --> <servlet> <!-- 指定DWR核心Servlet的名字 --> <servlet-name>dwr</servlet-name> <servlet-class> <!-- 指定DWR核心Servlet的实现类 --> org.directwebremoting.servlet.DwrServlet </servlet-class> <!-- 指定DWR核心Servlet处于调试状态 --> <init-param> <param-name>debug</param-name> <param-value>true</param-value> </init-param> <!-- 设置使用反向Ajax技术 --> <init-param> <param-name>activeReverseAjaxEnabled</param-name> <param-value>true</param-value> </init-param> <init-param> <param-name> initApplicationScopeCreatorsAtStartup </param-name> <param-value>true</param-value> </init-param> <init-param> <!--长连接只保持时间 --> <param-name>maxWaitAfterWrite</param-name> <param-value>60</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <!-- 指定核心Servlet的URL映射 --> <servlet-mapping> <servlet-name>dwr</servlet-name> <url-pattern>/dwr/*</url-pattern> </servlet-mapping> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> </web-app>第三步,在web.xml同目录下创建dwr的配置文件dwr.xml,具体代码如下:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE dwr PUBLIC "-//GetAhead Limited//DTD Direct Web Remoting 3.0//EN" "http://getahead.org/dwr/dwr30.dtd"> <dwr> <allow> <filter class="org.directwebremoting.filter.AuditLogAjaxFilter"></filter> <create javascript="SendMessage" creator="new" scope="application"> <param name="class" value="com.ajax.dwr.SendMessage"></param> </create> </allow> </dwr>
第四步,创建java文件,代码如下:
package com.ajax.dwr; import java.util.LinkedList; import java.util.List; import org.directwebremoting.Browser; import org.directwebremoting.ScriptSessions; public class SendMessage { public void addMessage(String message) { System.out.println("有客户请求,消息为:" + message); messages.add(message); Browser.withCurrentPage(new Runnable() {// 启用监听客户端当前页线程 public void run() {// 把数据添加到客户端调用的方法中 ScriptSessions.addFunctionCall("receiveMessages",messages); } }); } private List<String> messages = new LinkedList<String>(); }
第五步,创建Message.jsp文件,代码如下:
<html> <head> <title>starting page</title> <script type="text/javascript" src="dwr/interface/SendMessage.js"></script> <script type="text/javascript" src="dwr/engine.js"></script> <script type="text/javascript" src="dwr/util.js"></script> <script type="text/javascript"> function sendMessage() { var message=$("message").value; SendMessage.addMessage(message); } function receiveMessages(messages) { var chatlog = ""; for (var data in messages) { chatlog = "<div>" + dwr.util.escapeHtml(messages[data]) + "</div>" + chatlog; } dwr.util.setValue("list",chatlog,{ escapeHtml:false }); } </script> </head> <body onload="dwr.engine.setActiveReverseAjax(true);"> input message: <input id="message" type="text" /> <input type="button" value="send" onclick="sendMessage()" /> <br> <div id="list"></div> </body> </html>