一、实现原理剖析:
1.在群聊中,我们知道如何通过uri获得所有的session集合,但在单对单的聊天中并不需要获取全部,他只需要在彼此的session中进行聊天的管理/展示。
2.为此我们通过构造Map集合,通过单独唯一的key(用户名或者id编号,唯一即可),并同时将当前的session,put进去便可。当我们要指定发送对象时,我们便可获取
被发送对象的session,构建util。调用客户端编写好的js响应方法,产生相应的气泡提示了。
流程:Map构建-》发送消息给指定对象-》通过Map来get对象的session-》通过session构建utli-》util对客户端的js进行调用
ps:前提我们知道dwr中的远程调用Java类是单例模式下的。否则根本无法保存每一个session。
二、实现核心代码:
1.远程调用类:
public class MsgPushService { public static Map<String,Object> sessionManager = new HashMap<String,Object>(); /** * 添加客户端session ps:firfox有错误提示..-已解决,将跳转放置dwr的回调函数中 * 1.登录成功后进行调用 * @param username */ public String addScriptSession(String username,HttpServletRequest req) { if(!"".equals(username)&&username!=null){ sessionManager.put(username,WebContextFactory.get().getScriptSession()); } return "ok"; } public ScriptSession getScriptSession(String username) { return (ScriptSession) sessionManager.get(username); } /** * 2.发送消息时进行调用 * @param senderName * @param receiverName * @param title * @param content * @return */ @SuppressWarnings("unchecked") public String pushMsg(String senderName,String receiverName,String title,String content,HttpServletRequest req) { ScriptSession receiver_session = this.getScriptSession(receiverName); Collection<ScriptSession> cols = new ArrayList<ScriptSession>(); cols.add(receiver_session); Util util = new Util(cols); util.addFunctionCall("doReply","ok"); return "ok"; } /** * * 这里暂时没有用到:给所有客户端页面添加脚本 * @param function * @param msg * @param req * @return */ @SuppressWarnings("unchecked") public String addFunctionCallOnAllScriptSession(final String function,final String msg,HttpServletRequest req) { ServletContext sc = req.getSession().getServletContext(); ServerContext sctx = ServerContextFactory.get(sc); Collection<ScriptSession> sessions = sctx .getScriptSessionsByPage("/msgpush/jsp/msgPush.do"); Util util = new Util(sessions); util.addFunctionCall(function,msg); return "ok"; } }
2.页面调用:
<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%> <%@taglib uri="/struts-tags" prefix="s"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <Meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>欢迎 ${sessionScope.user.username }</title> <link rel="stylesheet" href="../js/poshytip-1.1/tip-darkgray/tip-darkgray.css" type="text/css" /> <script type='text/javascript' src='../dwr/engine.js'> </script> <script type='text/javascript' src='../dwr/interface/MsgPushService.js'> </script> <script type='text/javascript' src='../dwr/util.js'> </script> <script type="text/javascript" src="../js/jquery.js"></script> <script type="text/javascript" src="../js/msgpush.js"></script> <script type="text/javascript" src="../js/poshytip-1.1/jquery.poshytip.js"></script> </head> <body> <a id="notice" title="">消息通知中心</a> <a href="sessionMgmt.do?pageIndex=0" onclick="hide();" target="_blank">会话管理中心</a> <hr> 在线用户列表: <s:iterator value="#application.OnlineUsers" id="user"> <span id="<s:property value='#user' />"> <input type="radio" name="rusers" value="<s:property value='#user' />"/> <s:property value='#user' /> </span> </s:iterator> <s:if test="#application.OnlineUsers.size==1"> 暂没有可发送消息的对象 </s:if> <hr> <form> <table> <tr> <td>消息内容:</td> <td> <input type="text" id="title"/> </td> </tr> <!-- <tr> <td>内容</td> <td> <textarea rows="3" cols="20" id="content" ></textarea> </td> </tr> --> <tr> <td></td> <td> <input type="button" value="发送" onclick="javascript:pushMsg();"/> <input type="reset" value="清空"/> </td> </tr> </table> </form> <input type="hidden" value="${sessionScope.user.username }" id="username"/> </body> </html>
3.脚本处理
$(function(){ //在线用户列表中过滤本身 var id="#"+$("#username").val(); $(id).css("display","none"); }); function pushMsg(){ var title=$("#title").val(); //var content=$("#content").val(); var receiverName=$(":radio:checked").val(); if (receiverName == undefined) { alert("请选择发送的对象"); return; } if (title == "" || title.length <= 0) { alert("请输入主题"); return; } /* if (content == "" || content.length <= 0) { alert("请输入内容"); return; } */ /* MsgPushService.send($("#username").val(),$(":radio:checked").val(),$("#title").val(),$("#content").val(),{ //指定回调函数 callback:getMsg,//指定超时时长 timeout:1000,//指定错误处理函数 errorHandler:function(message) { alert("错误提示: " + message); },//指定 warningHandler:function(message) { alert("Oops: " + message); },textHtmlHandler: function(message) { alert("Oops: " + message); },exceptionHandler: function(message) { alert("Oops: " + message); },//指定发送请求的方式 httpMethod:'POST',async:true,//指定发送请求之前的勾子函数 preHook:function(){ //alert('远程调用之前...') },//指定发送请求之后的勾子函数 postHook:function(){ //alert('远程调用之后...') } }); */ MsgPushService.pushMsg($("#username").val(),receiverName,title,"",function(msg){ //alert(msg); }); //MsgPushService.test(); } function getMsg(msg){ //alert(msg); } function doReply(msg){ if('ok'==msg){ $('#notice').poshytip({ className: 'tip-darkgray',showOn:'none',//一直显示 content:'你有新消息 <a href="sessionMgmt.do?pageIndex=0" onclick="hide();" target="_blank">查看留言</a>',alignTo:'target',//定位的相对目标 alignX:'right',alignY:'center',offsetX:5 }); $('#notice').poshytip('show'); } } function hide(){ $('#notice').poshytip('hide'); } /** * 页面初始化 */ function init() { dwr.engine.setActiveReverseAjax(true); // 激活反转 重要 MsgPushService.addScriptSession($("#username").val(),function(msg){}); } window.onload = init;//页面加载完毕后执行初始化方法init
效果图: