DWR会在页面链接后台时,创建一个对应的ScriptSession对象,通过调用对应ScriptSession的scriptSession.addScript(script);方法来进行消息推送。
可以在相应的scriptSession中添加“name“属性来区分推送的目标,实现精确推送。
org.directwebremoting.Browser :http://directwebremoting.org/dwr/javadoc/org/directwebremoting/Browser.html
以下代码是在 DWR实现消息广播 的基础上进行改造的。
一、后台改造
1.在后台代码中增加onPageLoad方法,在scriptSession中增加推送的唯一标识。
2.利用ScriptSessionFilter对所有的scriptSession进行过滤。
3.向符合条件的页面进行推送
com.test.Message.java
package com.test; import java.util.Collection; import org.directwebremoting.Browser; import org.directwebremoting.ScriptBuffer; import org.directwebremoting.ScriptSession; import org.directwebremoting.ScriptSessionFilter; import org.directwebremoting.WebContextFactory; public class Message { // 载入页面时调用,传入name值作为推送的标识 public void onPageLoad(String name) { ScriptSession session = WebContextFactory.get().getScriptSession(); session.setAttribute("name", name); } public void addMessage(String userid, String message) { final String userId = userid; final String autoMessage = message; ScriptSession session = WebContextFactory.get().getScriptSession(); final String from = session.getAttribute("name").toString(); System.out.println("From: " + from + ", To: " + userid + ", Msg: " + message); // 通过ScriptSessionFilter筛选符合条件的ScriptSession Browser.withAllSessionsFiltered(new ScriptSessionFilter() { // 实现match方法,条件为真为筛选出来的session public boolean match(ScriptSession session) { String name = session.getAttribute("name").toString(); return name == null ? false : userId.equals(name); } }, new Runnable() { private ScriptBuffer script = new ScriptBuffer(); public void run() { // 设定前台接受消息的方法和参数 script.appendCall("receiveMessages", autoMessage); Collection<ScriptSession> sessions = Browser .getTargetSessions(); // 向所有符合条件的页面推送消息 for (ScriptSession scriptSession : sessions) { if (scriptSession.getAttribute("name").equals(userId)) { scriptSession.addScript(script); } } } }); } }
二、前台改造
1.引入了jquery,方便dom操作,由DwrServlet生成的 util.js 也具有dom操作功能。
2.在页面加载完毕之后,做了三件事:
2.1.dwr.engine.setActiveReverseAjax(true),开启逆向Ajax模式,在 DWR实现消息广播 例子中,写在body标签的onload方法中
2.2.dwr.engine.setNotifyServerOnPageUnload(true),这个方法设置DWR在页面关闭时销毁后台无效的ScriptSession,也可以使用setNotifyServerOnPageUnload(true, true)方法异步通知后台该ScriptSession无效。如果设置为false或者通知后台失败,将会采用延时销毁策略,以保证后台的ScriptSession都是有效的。
2.3.调用后台的onPageLoad方法,设置url中的name属性为推送唯一标识
在我本机的访问地址为 http://localhost:8080/Dwr-comet/index.jsp?name=a
index.jsp
<html> <head> <title>DWR - cometDemo</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> <script type="text/javascript" src="js/jquery-1.4.2.js"></script> <script type="text/javascript"> var chatlog = ""; function sendMessage() { var message = $("#message").val(); var user = $("#user").val(); // 通过代理调用后台的addMessage方法发送消息 Message.addMessage(user, message); } // 前台接受消息的方法,由后台调用 function receiveMessages(messages) { var lastMessage = messages; chatlog = "<p>" + lastMessage + "</p>" + chatlog; $("#list").html(chatlog); } //读取name值作为推送的唯一标示 function onPageLoad(){ // 获取URL中的name属性为唯一标识符 var userId = getQueryString("name"); $("#myName").html(userId); // 通过代理,传入区别本页面的唯一标识符 Message.onPageLoad(userId); } //获取url中的参数 function getQueryString(name) { var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)", "i"); var r = window.location.search.substr(1).match(reg); if (r != null) return unescape(r[2]); return null; } $(document).ready(function(){ dwr.engine.setActiveReverseAjax(true);// 开启逆向Ajax,也可写在body标签的onload方法中 dwr.engine.setNotifyServerOnPageUnload(true); onPageLoad(); }); </script> </head> <body> My name is:<span id="myName" style="color:red"></span><br/> To:<br/> <input id="user" type="text" /><br/> input message:<br/> <input id="message" type="text" value="hey" /> <input type="button" value="send" onclick="sendMessage()" /> <br> <div id="list"></div> </body> </html>
三、运行效果
打开一个name为a的窗口,两个name为b的窗口,a向b发送的消息两个b窗口都能收到推送,而b发给a的消息,只有a窗口接收到了推送。
控制台显示如下:
可以维护一个在线用户的Map来控制用户的唯一性,这需要定义一个简单的协议,以区分消息是通知用户下线还是发送的消息,稍后我会写一篇博客来实现这个Demo。
原文:http://www.cnblogs.com/nianzecong/p/3647399.html