SpringBoot 使用WebSocket打造在線聊天室(基於註解) 學習目標 快速查閱 使用教程

推薦WebSocket的三大理由:

  • 1、採用全雙工通信,擺脫傳統HTTP輪詢的窘境。
  • 2、採用W3C國際標準,完美支持HTML5。
  • 3、簡單高效,容易上手。

學習目標

快速學會通過WebSocket編寫簡單聊天功能。

快速查閱

專題閱讀:《SpringBoot 佈道系列》

源碼下載:SpringBoot-WebSocket-Chat

溫馨提示:
1、WebSocket是HTML5開始提供的一種在單個 TCP 連接上進行全雙工通訊的協議。在WebSocket API中,瀏覽器和服務器只需要做一個握手的動作,然後,瀏覽器和服務器之間就形成了一條快速通道。兩者之間就直接可以數據互相傳送。
2、瀏覽器通過 JavaScript 向服務器發出建立 WebSocket 連接的請求,連接建立以後,客戶端和服務器端就可以通過 TCP 連接直接交換數據。
3、當你獲取 Web Socket 連接後,你可以通過 send() 方法來向服務器發送數據,並通過 onmessage 事件來接收服務器返回的數據。

使用教程

一、打造 WebSocket 聊天客戶端

溫馨提示:得益於W3C國際標準的實現,我們在瀏覽器JS就能直接創建WebSocket對象,再通過簡單的回調函數就能完成WebSocket客戶端的編寫,非常簡單!接下來讓我們一探究竟。

使用說明:

使用步驟:1、獲取WebSocket客戶端對象。

例如: var webSocket = new WebSocket(url);

使用步驟:2、獲取WebSocket回調函數。

例如:webSocket.onmessage = function (event) {console.log('WebSocket收到消息:' + event.data);

事件類型 WebSocket回調函數 事件描述
open webSocket.onopen 當打開連接後觸發
message webSocket.onmessage 當客戶端接收服務端數據時觸發
error webSocket.onerror 當通信異常時觸發
close webSocket.onclose 當連接關閉時觸發

使用步驟:3、發送消息給服務端

例如:webSokcet.send(jsonStr) 結合實際場景 本案例採用JSON字符串進行消息通信。

具體實現:

下面是本案例在線聊天的客戶端實現的JS代碼,附帶詳細註釋。

<script>

    /**
     * WebSocket客戶端
     *
     * 使用說明:
     * 1、WebSocket客戶端通過回調函數來接收服務端消息。例如:webSocket.onmessage
     * 2、WebSocket客戶端通過send方法來發送消息給服務端。例如:webSocket.send();
     */
    function getWebSocket() {
        /**
         * WebSocket客戶端 PS:URL開頭表示WebSocket協議 中間是域名端口 結尾是服務端映射地址
         */
        var webSocket = new WebSocket('ws://localhost:8080/chat');
        /**
         * 當服務端打開連接
         */
        webSocket.onopen = function (event) {
            console.log('WebSocket打開連接');
        };

        /**
         * 當服務端發來消息:1.廣播消息 2.更新在線人數
         */
        webSocket.onmessage = function (event) {
            console.log('WebSocket收到消息:%c' + event.data, 'color:green');
            //獲取服務端消息
            var message = JSON.parse(event.data) || {};
            var $messageContainer = $('.message-container');
            //喉嚨發炎
            if (message.type === 'SPEAK') {
                $messageContainer.append(
                    '<div class="mdui-card" style="margin: 10px 0;">' +
                    '<div class="mdui-card-primary">' +
                    '<div class="mdui-card-content message-content">' + message.username + ":" + message.msg + '</div>' +
                    '</div></div>');
            }
            $('.chat-num').text(message.onlineCount);
            //防止刷屏
            var $cards = $messageContainer.children('.mdui-card:visible').toArray();
            if ($cards.length > 5) {
                $cards.forEach(function (item, index) {
                    index < $cards.length - 5 && $(item).slideUp('fast');
                });
            }
        };

        /**
         * 關閉連接
         */
        webSocket.onclose = function (event) {
            console.log('WebSocket關閉連接');
        };

        /**
         * 通信失敗
         */
        webSocket.onerror = function (event) {
            console.log('WebSocket發生異常');

        };
        return webSocket;
    }

    var webSocket = getWebSocket();


    /**
     * 通過WebSocket對象發送消息給服務端
     */
    function sendMsgToServer() {
        var $message = $('#msg');
        if ($message.val()) {
            webSocket.send(JSON.stringify({username: $('#username').text(), msg: $message.val()}));
            $message.val(null);
        }

    }
    /**
     * 清屏
     */
    function clearMsg(){
      $(".message-container").empty();
    }

    /**
     * 使用ENTER發送消息
     */
    document.onkeydown = function (event) {
        var e = event || window.event || arguments.callee.caller.arguments[0];
        e.keyCode === 13 && sendMsgToServer();
    };
</script>

========================================================================

二、打造 WebSocket 聊天服務端

溫馨提示:得益於SpringBoot提供的自動配置,我們只需要通過簡單註解@ServerEndpoint就就能創建WebSocket服務端,再通過簡單的回調函數就能完成WebSocket服務端的編寫,比起客戶端的使用同樣非常簡單!

使用說明:

首先在POM文件引入spring-boot-starter-websocket 、thymeleaf 、FastJson等依賴。

使用步驟:1、開啓WebSocket服務端的自動註冊。

這裏需要特別提醒:ServerEndpointExporter 是由Spring官方提供的標準實現,用於掃描ServerEndpointConfig配置類和@ServerEndpoint註解實例。使用規則也很簡單:1.如果使用默認的嵌入式容器 比如Tomcat 則必須手工在上下文提供ServerEndpointExporter。2. 如果使用外部容器部署war包,則不要提供提供ServerEndpointExporter,因爲此時SpringBoot默認將掃描服務端的行爲交給外部容器處理。

@Configuration
public class WebSocketConfig {
    @Bean
    public ServerEndpointExporter serverEndpointExporter() {

        return new ServerEndpointExporter();
    }
}

使用步驟:2、創建WebSocket服務端。

核心思路:

  • ① 通過註解@ServerEndpoint來聲明實例化WebSocket服務端。
  • ② 通過註解@OnOpen、@OnMessage、@OnClose、@OnError 來聲明回調函數。
事件類型 WebSocket服務端註解 事件描述
open @OnOpen 當打開連接後觸發
message @OnMessage 當接收客戶端信息時觸發
error @OnError 當通信異常時觸發
close @OnClose 當連接關閉時觸發
  • ③ 通過ConcurrentHashMap保存全部在線會話對象。
@Component
@ServerEndpoint("/chat")//標記此類爲服務端
public class WebSocketChatServer {

    /**
     * 全部在線會話  PS: 基於場景考慮 這裏使用線程安全的Map存儲會話對象。
     */
    private static Map<String, Session> onlineSessions = new ConcurrentHashMap<>();


    /**
     * 當客戶端打開連接:1.添加會話對象 2.更新在線人數
     */
    @OnOpen
    public void onOpen(Session session) {
        onlineSessions.put(session.getId(), session);
        sendMessageToAll(Message.jsonStr(Message.ENTER, "", "", onlineSessions.size()));
    }

    /**
     * 當客戶端發送消息:1.獲取它的用戶名和消息 2.發送消息給所有人
     * <p>
     * PS: 這裏約定傳遞的消息爲JSON字符串 方便傳遞更多參數!
     */
    @OnMessage
    public void onMessage(Session session, String jsonStr) {
        Message message = JSON.parseObject(jsonStr, Message.class);
        sendMessageToAll(Message.jsonStr(Message.SPEAK, message.getUsername(), message.getMsg(), onlineSessions.size()));
    }

    /**
     * 當關閉連接:1.移除會話對象 2.更新在線人數
     */
    @OnClose
    public void onClose(Session session) {
        onlineSessions.remove(session.getId());
        sendMessageToAll(Message.jsonStr(Message.QUIT, "", "下線了!", onlineSessions.size()));
    }

    /**
     * 當通信發生異常:打印錯誤日誌
     */
    @OnError
    public void onError(Session session, Throwable error) {
        error.printStackTrace();
    }

    /**
     * 公共方法:發送信息給所有人
     */
    private static void sendMessageToAll(String msg) {
        onlineSessions.forEach((id, session) -> {
            try {
                session.getBasicRemote().sendText(msg);
            } catch (IOException e) {
                e.printStackTrace();
            }
        });
    }

}
  • ④ 通過會話對象 javax.websocket.Session 來發消息給客戶端。
/**
 * WebSocket 聊天消息類
 */
package com.hehe.chat;

import com.alibaba.fastjson.JSON;

/**
 * WebSocket 聊天消息類
 */
public class Message {

    public static final String ENTER = "ENTER";
    public static final String SPEAK = "SPEAK";
    public static final String QUIT = "QUIT";

    private String type;//消息類型

    private String username; //發送人

    private String msg; //發送消息

    private int onlineCount; //在線用戶數

    public static String jsonStr(String type, String username, String msg, int onlineTotal) {
        return JSON.toJSONString(new Message(type, username, msg, onlineTotal));
    }

    public Message(String type, String username, String msg, int onlineCount) {
        this.type = type;
        this.username = username;
        this.msg = msg;
        this.onlineCount = onlineCount;
    }

    //這裏省略get/set方法 請自行補充
}

三、WebSocket在線聊天案例的視頻演示

1、源碼下載

至此,我們完成了客戶端和服務端的編碼,由於篇幅有限,本教程的頁面代碼並未完整貼上,想要完整的體驗效果請在Github下載源碼。傳送門:springboot-websocket-chat

2、視頻演示

上面一頓操作猛如虎,實際到底是啥樣子呢,接下來由哈士奇童鞋爲我們演示最終版的在線聊天案例:


四、全文總結

1、使用WebSocket用於實時雙向通訊的場景,常見的如聊天室、跨系統消息推送等。

2、創建WebSocket客戶端使用JS內置對象+回調函數+send方法發送消息。

3、創建WebSocket服務端使用註解聲明實例+使用註解聲明回調方法+使用Session發送消息。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章