RT,简单的实现了群聊和私聊,暂时私聊做的是一对一的,一对多可以简单重写过滤类。
支持快捷键发送消息。私聊直接点击对应用户名称即可。
下面介绍几个重要的文件。
web.xml
... <servlet> <servlet-name>dwrInvoker</servlet-name> <servlet-class> org.directwebremoting.servlet.DwrServlet </servlet-class> <init-param> <param-name>debug</param-name> <param-value>true</param-value> </init-param> <init-param> <description>使用服务器推技术(反转AJAX)</description> <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>100</param-value> </init-param> <load-on-startup>4</load-on-startup> <init-param> <param-name>classes</param-name> <param-value>java.lang.Object</param-value> </init-param> <load-on-startup>10</load-on-startup> </servlet> <servlet-mapping> <servlet-name>dwrInvoker</servlet-name> <url-pattern>/dwr/*</url-pattern> </servlet-mapping> ...
dwr.xml
... <!-- AJAX技术具体实现 --> <allow> <!-- convert将bean的集合变成javascript中的对象数组--> <convert converter="bean" match="com.User"></convert> <!-- 业务处理类 --> <create creator="new" javascript="mydwr" scope="session"> <param name="class" value="com.IndexAction" /> </create> </allow> ...
后台处理IndexAction.java
... public User userLogin(String name, String id) { if (name == null || name.trim().length() == 0) { name = "匿名用户"; id = String.valueOf(new Date().getTime()); } User user = new User(name, id); list.add(user); show(user); WebContextFactory.get().getScriptSession().setAttribute("userId", id); return user; } private void show(final User user) { try { String page = ServerContextFactory.get().getContextPath() + "/indexs.jsp"; Browser.withPage(page, new Runnable() { public void run() { System.out.println("开始添加用户 "); // ScriptSessions.addFunctionCall("tsess","abddd"); ScriptSessions.addFunctionCall("showNew", user.getName(), user.getId()); System.out.println("添加用户END "); } }); } catch (Exception e) { e.printStackTrace(); } } public void sendMsg(final String sender, final String msg) { try { System.out.println(sender + msg); String page = ServerContextFactory.get().getContextPath() + "/indexs.jsp"; Browser.withPage(page, new Runnable() { public void run() { ScriptSessions.addFunctionCall("handMsg_show", sender, msg); } }); } catch (Exception e) { e.printStackTrace(); Thread.currentThread().interrupt(); } } public void sendMsg_Private(final String userId, final String sender, final String msg) { try { System.out.println("private " + userId); String page = ServerContextFactory.get().getContextPath() + "/indexs.jsp"; Browser.withPageFiltered(page, new MyScriptSessionFilter(userId), new Runnable() { public void run() { System.out.println("haha"); ScriptSessions.addFunctionCall( "handMsg_show_private", sender, getUserName(userId), msg); } }); } catch (Exception e) { e.printStackTrace(); Thread.currentThread().interrupt(); } } ...
User是一个简单的java对象,只有id和name俩字符串型属性。
过滤类MyScriptSessionFilter.java实现ScriptSessionFilter接口即可
... public boolean match(ScriptSession session) { if (userId == null || userId.trim().length() == 0) return true; String _userId = (String) session.getAttribute("userId"); if (!userId.equalsIgnoreCase(_userId)) return false; return true; } ...
展示页面就直接拷贝出来了
<html> <head> <base href="<%=basePath%>"> <title>DWR DEMO</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <!-- <link rel="stylesheet" type="text/css" href="styles.css"> --> </head> <script type='text/javascript' src='./dwr/util.js'></script> <script type='text/javascript' src='./dwr/engine.js'></script> <script type='text/javascript' src='./dwr/interface/mydwr.js'></script> <script type='text/javascript' src='./js/jquery/jquery.js'></script> <script type='text/javascript' src='./js/indexs.js'></script> <style type="text/css"> .senderc { font-size: 12px; font-weight: bold; } .msgc { color: blue; padding-left: 20; } .msg_userExitc { color: red; font-weight: bold; font-size: 14; } </style> <body> <table height="100%" width="100%" border="1"> <tr> <td valign="top" width="30%"> <b>用户信息</b> <br> NAME: <input type="text" id="userName" value=""> <input type="button" onclick="javascript:editUser();" value="修改用户名"> <br> ID: <label id="userId"></label> <br> <b>用户列表</b> <table width="100%"> <tr> <td> <div id="userList" style="height: 700; overflow-y: scroll; border: 1px solid;"> </div> </td> </tr> </table> </td> <td valign="top"> <span style="color: blue;">群聊信息</span> <div id="showMsg_All" style="height: 300; overflow-y: scroll; border: 1px solid; border-bottom: 10px; background-color: #E4EC60;"> </div> <span style="color: blue;">私聊信息</span> <div id="showMsg_Self" style="height: 200; border-bottom: 10px; background-color: #F7F9CE; overflow-y: scroll; border: 1px solid;"> </div> <br> <div id="inputDiv"> <textarea id="inputMsg" style="width: 100%; height: 150;" rows="" cols=""></textarea> </div> <br> <div align="right"> <input type="checkbox" id="ctrl_enter" /> <label for="ctrl_enter"> Ctrl+Enter发送消息 </label> <input type="checkbox" id="enter" /> <label for="enter"> Enter发送消息 </label> <input type="button" id="send" onclick="javascript:sendMsg();" name="send" value="发送"> </div> </td> </tr> </table> </body> </html>
所有的js文件,也直接拷贝了
var showMsg_All; var showMsg_Self; $(document).ready(function() { showMsg_All = $("#showMsg_All"); showMsg_Self = $("#showMsg_Self"); dwr.engine.setActiveReverseAjax(true); mydwr.userLogin(bindUser); mydwr.getList(showUsers); $("#ctrl_enter").click(function() { if (this.checked) { $("#enter").attr("checked", false); $("#inputMsg").unbind("keydown", enter); $("#inputMsg").bind("keydown", ctrl_enter); } else { $("#inputMsg").unbind("keydown", ctrl_enter); } }); $("#enter").click(function() { if (this.checked) { $("#ctrl_enter").attr("checked", false); $("#inputMsg").unbind("keydown", ctrl_enter); $("#inputMsg").bind("keydown", enter); } else { $("#inputMsg").unbind("keydown", enter); } }); }) ctrl_enter = function(event) { if (event.ctrlKey && event.keyCode == 13) { sendMsg(); event.returnValue = false; return false; } } enter = function(event) { if (event.keyCode == 13) { if (event.ctrlKey) { return true; } else { sendMsg(); event.returnValue = false; return false; } } } showUsers = function(data) { if (data) { for (var i = 0; i < data.length; i++) { if (data[i].id == $("#userId").text()) { continue; } var user = "<div id='" + data[i].id + "' style='cursor:pointer;' onclick='javascript:sendMsg_Private(this.id);'>" + data[i].id + "--" + data[i].name + "</div>"; $("#userList").append(user); } } } showNew = function(name, id) { if ($("#" + id).val() == null) { var user = "<div id='" + id + "'style='cursor:pointer;' onclick='javascript:sendMsg_Private(this.id);'>" + id + "--" + name + "</div>"; $("#userList").append(user); } } bindUser = function(user) { $("#userName").val(user.name); $("#userId").text(user.id); } callEditUser = function(id, name) { // alert(id+name); $("#" + id).html(id + "--" + name); } editUser = function() { var name = $("#userName").val(); var id = $("#userId").text(); mydwr.editUser(id, name); } handMsg_show = function(sender, msg) { // showMsg_All.append(sender + "说:<br>"); // showMsg_All.append(msg + "<br>"); showMsg_All.append(handMsg_sender(sender)); showMsg_All.append(handMsg_msg(msg)); } handMsg_sender = function(sender, receiver) { if (receiver == null || receiver == '' || receiver == 'undefined') receiver = "大家"; var sender = "<div class='senderc'>" + sender + " 对 " + receiver + " 说:" + "</div>"; return sender; } handMsg_msg = function(msg) { var msg = "<div class='msgc'>" + msg + "</div>"; return msg; } handMsg_userExit = function(userId) { var user = $("#" + userId).text(); var msg = "<div class='msg_userExitc'>" + user + " 用户退出</div>"; return msg; } handMsg_show_private = function(sender, receiver, msg) { // showMsg_Self.append(sender + " 对 " + receiver + " 说:<br>"); showMsg_Self.append(handMsg_sender(sender, receiver)); // showMsg_Self.append(msg + "<br>"); showMsg_Self.append(handMsg_msg(msg)); } sendMsg = function() { var msg = $("#inputMsg").val(); var sender = $("#userName").val(); if (checkMsg_null(msg)) { mydwr.sendMsg(sender, msg); $("#inputMsg").val(""); } } sendMsg_Private = function(receiver) { var msg = $("#inputMsg").val(); var sender = $("#userName").val(); if (checkMsg_null(msg)) { mydwr.sendMsg_Private(receiver, sender, msg); var _receiver = $("#" + receiver).text(); handMsg_show_private(sender, _receiver, msg); $("#inputMsg").val(""); } } window.onbeforeunload = function() { var warning = "您输入的数据可能不会被保存,确认退出?"; return warning; } window.onunload = function() { mydwr.userExit($("#userId").text()); var warning = "谢谢光临"; alert(warning); } removeUser = function(userId) { showMsg_All.append(handMsg_userExit(userId)); $("#" + userId).remove(); } checkMsg_null = function(msg) { if (msg == null || msg == 'undefined' || $.trim(msg).length == 0) { alert("请不要发送空消息!"); return false; } return true; }
OK,其实我也是初学者,文中可能有些实现不是最优的,请大家指教,共同学习。