采用DWR推送技术+消息队列的局域网聊天工具
采用DWR推送技术+消息队列,前端通过jquery 追加消息。具体实现细节如下:
部分源码:
消息推送后台代码 package com.qunyiinfo.chat.common.task; import java.util.Collection; import java.util.LinkedList; import java.util.concurrent.locks.ReentrantLock; import org.directwebremoting.ScriptBuffer; import org.directwebremoting.ScriptSession; import org.directwebremoting.WebContext; import org.directwebremoting.WebContextFactory; import org.directwebremoting.proxy.dwr.Util; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; import com.qunyiinfo.chat.service.IChatService; import com.qunyiinfo.chat.web.form.MsgFrm; /** * 类PushMessageTask.java的实现描述:TODO 类实现描述 *伦理电影www.akdy.cn * @author shengshang.tang 2014年6月24日 上午10:10:29 */ @Component(value = "pushMessageTask") public class PushMessageTask { private static ReentrantLock lock = new ReentrantLock(); private volatile Boolean readyState = false; private WebContext contex = null; @Autowired private IChatService chatService; public void ready() { contex = WebContextFactory.get(); readyState = true; } /** * 推送消息 * <p> * 每5分钟扫描一次 */ @Scheduled(cron = "0/10 * * * * *") public void pushMessage() { lock.lock(); try { if (!readyState) { // 还么有准备好 return; } Collection<ScriptSession> sessions = contex.getScriptSessionsByPage("/chat/enterChat.htm"); Util util = new Util(sessions); ScriptBuffer sb = new ScriptBuffer(); // 获得聊天记录 LinkedList<MsgFrm> mll = chatService.getMsgList(); // 获得在线用户 Collection<String> personList = chatService.getPersonList(); sb.appendScript("showMsgList("); sb.appendData(mll); sb.appendScript(");"); sb.appendScript("showPersonList("); sb.appendData(personList); // 推送 util.addScript(sb); } catch (Exception e) { e.printStackTrace(); } finally { lock.unlock(); } } package com.qunyiinfo.chat.service.impl; import java.util.Map.Entry; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.LinkedBlockingDeque; import javax.servlet.http.HttpSession; import org.springframework.stereotype.Service; import com.apache.platform.common.ServeltContextManager; import com.apache.platform.common.ServeltContextManager.ServeltContext; import com.apache.platform.service.AbstractBaseService;
消息队列实现 * 类ChatServiceImpl.java的实现描述:TODO 类实现描述 * * @author shengshang.tang 2014年6月23日 下午2:50:07 @Service public class ChatServiceImpl extends AbstractBaseService implements IChatService { private static LinkedBlockingDeque<MsgFrm> stList = new LinkedBlockingDeque<MsgFrm>(100); private static LinkedBlockingDeque<MsgFrm> stHisList = new LinkedBlockingDeque<MsgFrm>(100); private static ConcurrentMap<String,String> personMap = new ConcurrentHashMap<String,String>(); @Override public Boolean join(HttpSession session,String username) { String sid = session.getId(); if (personMap.containsValue(username)) { return false; } else { personMap.put(sid,username); session.setAttribute(sid,sans-serif; font-size:14px; line-height:25.1875px"> return true; public Collection<String> getPersonList() { return personMap.values(); public void removeUserBySid(String sid) { if (personMap.containsKey(sid)) { personMap.remove(sid); public void sendMsg(String username,String content,String styleClass) { MsgFrm msgFrm = new MsgFrm(username,content,styleClass); stList.add(msgFrm); public LinkedList<MsgFrm> getMsgList() { int chatMsgSize = 50; // 申明一个输出队列 LinkedList<MsgFrm> ll = new LinkedList<MsgFrm>(); int curCount = 0; for (int i = 0; i < chatMsgSize && !stList.isEmpty(); i++) { MsgFrm msgFrm = stList.removeLast(); stHisList.addFirst(msgFrm); ll.addFirst(msgFrm); curCount++; // 新的队列中记录还有剩余,则放到老队列记录中 while (!stList.isEmpty()) { // 输出的队列记录不够,则从老队列中获取 if (ll.size() < chatMsgSize) { MsgFrm[] data = stHisList.toArray(new MsgFrm[] {}); int stepLen = chatMsgSize - ll.size(); for (int i = 0; i < stepLen && (i + curCount) < data.length; i++) { MsgFrm content = data[i + curCount]; ll.addFirst(content); return ll; public void removeExpiresUser() { ServeltContext sc = ServeltContextManager.get(); if (sc == null) { return; HttpSession session = sc.getRequest().getSession(); Set<Entry<String,String>> set = personMap.entrySet(); for (Entry<String,String> entry : set) { String sid = entry.getKey(); if (session.getAttribute(sid) == null) { // 已经过期 personMap.remove(sid); // 移除 前端JS+HTML chat.js $(document).ready(function() { $('#myTab a').click(function(e) { e.preventDefault(); $(this).tab('show'); }) //进入推送消息 pushMsgTask.pushMessage(); // 发送 $("#send").click(function() { // 加入 if (!$("#editForm").validate(vSettings)) { return; $.post("sendMsg.htm",{ msg : $("#msg").val() },function(data,textStatus) { if (data == "1") { // 清空当前发送区域消息 $("#msg").val(""); // 手动调用消息刷新 }); $(document).keypress(function(e) { if (e.ctrlKey && e.which == 13 || e.which == 10) { // ctrl +回车 发送 $("#send").trigger("click"); // 设置dwr推送技术 dwr.engine.setActiveReverseAjax(true); // 开始推送准备 pushMsgTask.ready(); // 校验 vSettings = { rules : { msg : { required : true, maxLength : 50 messages : { required : "不能发送空消息",sans-serif; font-size:14px; line-height:25.1875px"> maxLength : "消息不能超过50个字符" }; function showMsgList(data) { var array = new Array(); for (var i = 0; i < data.length; i++) { var msg = data[i]; array.push('<div class="chat_content_group">'); array.push('<p class="chat_nick">'+msg.username+'</p>'); array.push('<p class="chat_content">'); array.push(msg.content); array.push('</p>'); array.push("</div>"); $("#content").html(array.join("")); function showPersonList(data) { array.push("<p>"); array.push(msg); array.push("</p>"); $("#pl").html(array.join("")); $("#content").scrollTop($("#content")[0].scrollHeight); msg.vm <div class="main_container"> <div id="content" class="main_chat"> </div> <div class="person_list" > <div><h3>聊天成员</h3></div> <div id="pl"> </div> <div id="buttom"> <div class="txt_content"> <textarea id="msg" name="msg" style="width:100%;height:60px"></textarea> <div class="btn_send"> <input type="button" value="发送" class="btn btn_save" id="send" /> </div> (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |