DWR实现消息广播
1. Dwr后台向前台发送消息的三种方式
Dwr是允许java后台和前台javascript互相调用的java库。
反转ajax是DWR2.0的一个新特性,它提供从web服务器异步发送数据到浏览器的能力。
web的目的不是服务器连接浏览器,所以及时的获取数据给浏览器可能比较复杂。DWR3支持3种方式的数据push到浏览器:piggback,polling和comet。
1.2 Polling
轮询可以最直接明显的解决问题。这时浏览器发送服务器请求是有规律和间隔的,例如每3秒,看看是否有页面更新。
1.3 comet
comet允许服务器响应浏览器请求信息比较慢,并且取决于服务器的时间表。也就是长连接。
1.4 piggyback
简单的说就是服务器在下一次请求中返回数据。打个比方,a请求发送,服务器响应。过了一会服务器有新的数据,它会等待下一次b请求(可能不是a),将数据带回页面。存在问题不能及时交互。
1.5 三种方式比较
polling实现简单,但是服务器负载会加大。
comet数据及时响应,但是会造成资源浪费。
piggyback可以说是最好的方式,但是数据响应存在不定时性,取决客户端下次请求间隔。
在DWR中你可以根据需要选择其中的某种方式,comet和polling是比较极端的2个例子我们可以采取参数配置连接时间和轮询时间,以求解决服务器负载。
DWR中reverse ajax 分积极和消极2种。
积极方式包括comet和polling,也就是数据的及时响应。
DWR默认采用piggyback背包机制,也就是消极方式。
1.6 DWR下载
官方网站:http://directwebremoting.org/dwr/
当前最新版本为:DWR version 3.0.rc2
1.7 环境
Java JDK 1.6
Tomcat 6.0
Windows server 2008 32bit
Eclipse Indigo Service Release
支持jar包:
dwr.jar (version 3.0.rc2)
2 DWR配置
2.1 最小配置
web.xml
1 <?xml version="1.0" encoding="UTF-8"?> 2 <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 3 xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" 4 xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" 5 id="WebApp_ID" version="2.5"> 6 <servlet> 7 <!-- 指定DWR核心Servlet的名字 --> 8 <servlet-name>dwr</servlet-name> 9 <servlet-class> 10 <!-- 指定DWR核心Servlet的实现类 --> 11 org.directwebremoting.servlet.DwrServlet 12 </servlet-class> 13 </servlet> 14 <!-- 指定核心Servlet的URL映射 --> 15 <!—- dwr/* 的请求全都交给DwrServlet处理用以生成服务器的前台代理 --> 16 <servlet-mapping> 17 <servlet-name>dwr</servlet-name> 18 <url-pattern>/dwr/*</url-pattern> 19 </servlet-mapping> 20 <welcome-file-list> 21 <welcome-file>index.jsp</welcome-file> 22 </welcome-file-list> 23 </web-app>
dwr.xml
1 <?xml version="1.0" encoding="UTF-8"?> 2 <!DOCTYPE dwr PUBLIC 3 "-//GetAhead Limited//DTD Direct Web Remoting 3.0//EN" 4 "http://getahead.org/dwr/dwr30.dtd"> 5 <!—- 以上头文件版本需要和dwr.jar的版本相对应,这里是dwr3.0的配置 --> 6 <dwr> 7 <allow> 8 <!—- dwr会根据此配置生成对应java类的前台js代理 --> 9 <create javascript="Message" creator="new" scope="application"><param name="class" value="com.test.Message"></param> 10 </create> 11 </allow> 12 </dwr>
2.2 扩展配置
web.xml
1 <!-- 指定DWR核心Servlet处于调试状态 --> 2 <init-param> 3 <param-name>debug</param-name> 4 <param-value>true</param-value> 5 </init-param> 6 <!-- 设置使用反向Ajax技术 --> 7 <init-param> 8 <param-name>activeReverseAjaxEnabled</param-name> 9 <param-value>true</param-value> 10 </init-param> 11 <!--长连接只保持时间 --> 12 <init-param> 13 <param-name>maxWaitAfterWrite</param-name> 14 <param-value>60</param-value> 15 </init-param>
2.3 前台页面代码
index.jsp
<html> <head> <title>starting page</title> <script type="text/javascript" src="./dwr/engine.js"></script> <script type="text/javascript" src="./dwr/util.js"></script> <script type="text/javascript" src="./dwr/interface/Message.js"></script> <!-- 这三个js都是由dwr的servlet生成 --> <!-- Message.js是dwr生成的message.java的前台代理类 --> <!-- 需要注意的是,util.js中也运用$来操作dom,和jquery同时使用时存在多库共存问题,需要注意“$”符的控制权问题 --> <script type="text/javascript"> var messageList = ""; /* 通过代理调用后台发送消息的方法 */ function sendMessage() { var message = $("message").value; Message.addMessage(message); } /* 接受消息方法的前台代理 */ function receiveMessages(messages) { for ( var data in messages) { messageList = "<div>" + dwr.util.escapeHtml(messages[data]) + "</div>" + messageList; } dwr.util.setValue("list", messageList, { escapeHtml : false }); } </script> </head>
<!-- onload方法开启你想Ajax --> <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>
2.4 后台代码
com.test.Message.java
package com.test; import java.util.LinkedList; import java.util.List; import org.directwebremoting.Browser; import org.directwebremoting.ScriptSessions; public class Message { private List<String> messages = new LinkedList<String>(); public void addMessage(String message) { System.out.println("消息:" + message); messages.removeAll(messages); messages.add(message); Browser.withCurrentPage(new Runnable() {// 启用监听客户端当前页线程 public void run() {// 把数据添加到客户端调用的方法中 ScriptSessions.addFunctionCall("receiveMessages", messages); } }); } }
3. 运行结果