`

局域网聊天工具

阅读更多

 

 先看效果微笑

 



 

 

采用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 类实现描述

 * 

 * @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);

            sb.appendScript(");");

 

            // 推送

            util.addScript(sb);

        } catch (Exception e) {

            e.printStackTrace();

        } finally {

            lock.unlock();

        }

    }

}

 

package com.qunyiinfo.chat.service.impl;

 

import java.util.Collection;

import java.util.LinkedList;

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;

import com.qunyiinfo.chat.service.IChatService;

import com.qunyiinfo.chat.web.form.MsgFrm;

 

 

消息队列实现

 

/**

 * 类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, username);

            return true;

        }

    }

 

    @Override

    public Collection<String> getPersonList() {

        return personMap.values();

    }

 

    @Override

    public void removeUserBySid(String sid) {

        if (personMap.containsKey(sid)) {

            personMap.remove(sid);

        }

    }

 

    @Override

    public void sendMsg(String username, String content, String styleClass) {

        MsgFrm msgFrm = new MsgFrm(username, content, styleClass);

        stList.add(msgFrm);

    }

 

    @Override

    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()) {

            MsgFrm msgFrm = stList.removeLast();

            stHisList.addFirst(msgFrm);

        }

 

        // 输出的队列记录不够,则从老队列中获取

        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("");

// 手动调用消息刷新

pushMsgTask.pushMessage();

}

}, 'json');

});

 

$(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 : {

msg : {

required : "不能发送空消息",

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) {

var array = new Array();

for (var i = 0; i < data.length; i++) {

var msg = data[i];

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>

          </div>

 

          <div id="buttom">

            <div class="txt_content">

      <textarea id="msg" name="msg" style="width:100%;height:60px"></textarea>

</div>

            <div class="btn_send">

      <input type="button" value="发送" class="btn btn_save" id="send" />

</div>

 </div>

 

  • 大小: 16.8 KB
  • 大小: 1.3 KB
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics