websocket(二):SSM+websocket的聊天室


在github上面找了一個看起來還不錯的網頁版聊天室,基於ssm加websocket實現的,特此分享一下,github地址放在文章末尾,大家可以自行下載跑起來玩玩,項目如何跑起來我寫在readme里面了。接下來簡單的看一下項目和核心代碼的實現。

登錄頁面:

首頁:可以實現單人聊天和群聊,還有機器人自動回復功能,還有一些個人設置,系統設置功,日志統計功能...

 接下來看看核心代碼websocket的實現:

首頁jsp關於websocket的代碼:

 var wsServer = null;
    var ws = null;
    wsServer = "ws://" + location.host+"${pageContext.request.contextPath}" + "/chatServer/${userid}";
    ws = new WebSocket(wsServer); //創建WebSocket對象
    ws.onopen = function (evt) {
        layer.msg("已經建立連接", { offset: 0});
    };
    ws.onmessage = function (evt) {
        analysisMessage(evt.data);  //解析后台傳回的消息,並予以展示
    };
    ws.onerror = function (evt) {
        layer.msg("產生異常", { offset: 0});
    };
    ws.onclose = function (evt) {
        layer.msg("已經關閉連接," + evt.reason, { offset: 0});
    };

websocket server的實現;

package com.ccq.webSocket;

import com.ccq.pojo.User;
import com.ccq.utils.CommonDate;
import net.sf.json.JSONObject;
import org.apache.log4j.Logger;

import javax.servlet.http.HttpSession;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author ccq
 * @Description webSocket服務
 * @date 2017/12/16 17:31
 */
@ServerEndpoint(value="/chatServer/{userid}", configurator = HttpSessionConfigurator.class)
public class ChatServer {

    private static Logger logger = Logger.getLogger(ChatServer.class);
    private static int onlineCount = 0; // 記錄連接數目
    // Map<用戶id,用戶信息>
    private static Map<String, OnlineUser> onlineUserMap = new ConcurrentHashMap<String, OnlineUser>(); // 在線用戶

    /**
     * 連接成功調用的方法
     */
    @OnOpen
    public void onOpen(@PathParam("userid") String userid , Session session, EndpointConfig config){

        logger.info("[ChatServer] connection : userid = " + userid + " , sessionId = " + session.getId());

        // 增加用戶數量
        addOnlineCount();

        // 獲取當前用戶的session
        HttpSession httpSession = (HttpSession) config.getUserProperties().get(HttpSession.class.getName());
        User user  = (User) httpSession.getAttribute("user"); // 獲得當前用戶信息

        // 將當前用戶存到在線用戶列表中
        OnlineUser onlineUser = new OnlineUser(user.getUserid(),user.getNickname(),session);
        onlineUserMap.put(user.getUserid(),onlineUser);

        // 通知所有在線用戶,當前用戶上線
        String content = "[" + CommonDate.getTime24() + " : " + user.getNickname() + "加入聊天室,當前在線人數為 " + getOnlineCount() + "位" + "]";
        JSONObject msg = new JSONObject();
        msg.put("content",content);
        String message = Message.getMessage(msg.toString(),Message.NOTICE,onlineUserMap.values());
        Message.broadcast(message,onlineUserMap.values());

    }

    /**
     * 連接關閉方法
     */
    @OnClose
    public void onClose(@PathParam("userid") String userid,Session session,CloseReason closeReason){

        logger.info("[ChatServer] close : userid = " + userid + " , sessionId = " + session.getId() +
                " , closeCode = " + closeReason.getCloseCode().getCode() + " , closeReason = " +closeReason.getReasonPhrase());

        // 減少當前用戶
        subOnlienCount();

        // 移除的用戶信息
        OnlineUser removeUser = onlineUserMap.remove(userid);
        onlineUserMap.remove(userid);

        // 通知所有在線用戶,當前用戶下線
        String content = "["+ CommonDate.getTime24() + " : " + removeUser.getNickname() + " 離開聊天室,當前在線人數為 " + getOnlineCount() + "位" + "]";
        JSONObject msg = new JSONObject();
        msg.put("content",content);
        if(onlineUserMap.size() > 0){
            String message = Message.getMessage(msg.toString(), Message.NOTICE, onlineUserMap.values());
            Message.broadcast(message,onlineUserMap.values());
        }else{
            logger.info("content : ["+ CommonDate.getTime24() + " : " + removeUser.getNickname() + " 離開聊天室,當前在線人數為 " + getOnlineCount() + "位" + "]");
        }

    }

    /**
     * 接收客戶端的message,判斷是否有接收人而選擇進行廣播還是指定發送
     * @param data 客戶端發來的消息
     */
    @OnMessage
    public void onMessage(@PathParam("userid") String userid,String data){
        logger.info("[ChatServer] onMessage : userid = " + userid + " , data = " + data);

        JSONObject messageJson = JSONObject.fromObject(data);
        JSONObject message = messageJson.optJSONObject("message");
        String to = message.optString("to");
        String from = message.optString("from");
        // 將用戶id轉換為名稱
        to = this.userIdCastNickName(to);

        OnlineUser fromUser = onlineUserMap.get(from);
        String sendMessage = Message.getContent(fromUser,to,message.optString("content"),message.optString("time"));
        String returnData = Message.getMessage(sendMessage, messageJson.optString("type"),null);

        if(to == null || to.equals("")){ // 進行廣播
            Message.broadcast(returnData.toString(),onlineUserMap.values());
        }else{
            Message.singleSend(returnData.toString(), onlineUserMap.get(from));   // 發送給自己
            String[] useridList = message.optString("to").split(",");
            for(String id : useridList){
                if(!id.equals(from)){
                    Message.singleSend(returnData.toString(), onlineUserMap.get(id)); // 分別發送給指定的用戶
                }
            }
        }
    }

    /**
     * 發生錯誤
     * @param throwable
     */
    @OnError
    public void onError(@PathParam("userid") String userid,Session session,Throwable throwable){
        logger.info("[ChatServer] close : userid = " + userid + " , sessionId = " + session.getId() +" , throwable = " + throwable.getMessage() );
    }


    public static int getOnlineCount() {
        return onlineCount;
    }

    public synchronized void addOnlineCount(){
        onlineCount++;
    }

    public synchronized void subOnlienCount(){
        onlineCount--;
    }

    /**
     * 將用戶id轉換為名稱
     * @param userIds
     * @return
     */
    private String userIdCastNickName(String userIds){
        String niceNames = "";
        if(userIds != null && !userIds.equals("")){
            String[] useridList = userIds.split(",");
            String toName = "";
            for (String id : useridList){
                toName = toName + onlineUserMap.get(id).getNickname() + ",";
            }
            niceNames = toName.substring(0,toName.length() - 1);
        }
        return niceNames;
    }
}

私聊和群聊的發送代碼:

 /**
     * 廣播消息
     * @param message 消息
     * @param onlineUsers 在線用戶
     */
    public static void broadcast(String message,Collection<OnlineUser> onlineUsers){
        /***************************在線用戶***************************/
        StringBuffer userStr = new StringBuffer();
        for(OnlineUser user : onlineUsers){
            userStr.append(user.getNickname() + ",");
        }
        userStr.deleteCharAt(userStr.length()-1);
        logger.info("[broadcast] message = " + message + ", onlineUsers = " + userStr.toString());
        /***************************在線用戶***************************/
        for(OnlineUser user : onlineUsers){
                try {
                    user.getSession().getBasicRemote().sendText(message);
                } catch (IOException e) {
                    e.printStackTrace();
                    logger.info("消息發送失敗!" + e.getMessage());
                    continue;
                }
        }
    }

    /**
     * 對特定用戶發送消息
     * @param message
     * @param onlineUser
     */
    public static void singleSend(String message, OnlineUser onlineUser){
        logger.info("[singleSend] message = " + message + ", toUser = " + onlineUser.getNickname());
        try {
            onlineUser.getSession().getBasicRemote().sendText(message);
        } catch (IOException e) {
            e.printStackTrace();
            logger.info("消息發送失敗!" + e.getMessage());
        }
    }

記住幾個關鍵api:

OnOpen:建立連接
OnClose:關閉連接
OnMessage:接收消息
發送消息的核心方法是通過某個session的.getBasicRemote().sendText(message)來發送的。
ok,websocket大概就是這樣,你可以親自啊跑一下試試,也十分歡迎大家一起來豐富這個小項目,增加一些有趣的功能,讓大家欣賞,我會第一時間在github上面寫上你的大名,以表感謝。
github鏈接:https://github.com/MrLiu1227/WebChat.git
沒有基礎的同學可以跑一個十分干凈的websocket示例:https://github.com/MrLiu1227/websocket.git


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM