SpringBoot項目中,WebSocket的使用(觀察者設計模式)


1.什么是WebSocket(選擇至菜鳥教程(點擊跳轉),觀察者模式)

WebSocket 是 HTML5 開始提供的一種在單個 TCP 連接上進行全雙工通訊的協議。

WebSocket 使得客戶端和服務器之間的數據交換變得更加簡單,允許服務端主動向客戶端推送數據。在 WebSocket API 中,瀏覽器和服務器只需要完成一次握手,兩者之間就直接可以創建持久性的連接,並進行雙向數據傳輸。

在 WebSocket API 中,瀏覽器和服務器只需要做一個握手的動作,然后,瀏覽器和服務器之間就形成了一條快速通道。兩者之間就直接可以數據互相傳送。

現在,很多網站為了實現推送技術,所用的技術都是 Ajax 輪詢。輪詢是在特定的的時間間隔(如每1秒),由瀏覽器對服務器發出HTTP請求,然后由服務器返回最新的數據給客戶端的瀏覽器。這種傳統的模式帶來很明顯的缺點,即瀏覽器需要不斷的向服務器發出請求,然而HTTP請求可能包含較長的頭部,其中真正有效的數據可能只是很小的一部分,顯然這樣會浪費很多的帶寬等資源。

HTML5 定義的 WebSocket 協議,能更好的節省服務器資源和帶寬,並且能夠更實時地進行通訊。

2.創建WebSocket連接(被觀察者)

這里我們在前端頁面向后端頁面發出請求,JavaScript中定義了WebSocket

四個事件和兩個方法

<script>
    var websocket = null;
    if('WebSocket' in window) {
        websocket = new WebSocket('ws://localhost:8080/sell/webSocket');
    }else {
        alert('該瀏覽器不支持websocket!');
    }

    websocket.onopen = function (event) {
        console.log('建立連接');
    }

    websocket.onclose = function (event) {
        console.log('連接關閉');
    }

    websocket.onmessage = function (event) {
        console.log('收到消息:' + event.data)
        //彈窗提醒,
        $('#myModal').modal('show');
        // 播放音樂
        document.getElementById('notice').play();
    }

    websocket.onerror = function () {
        alert('websocket通信發生錯誤!');
    }

    window.onbeforeunload = function () {
        websocket.close();
    }

</script>

3.使用java創建WebSokect連接(觀察者)

 3.1引入依賴

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-websocket</artifactId>
        </dependency>

3.2注入ServerEndpointExporter(注入環境)

package com.xiong.sell.config;

import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;


@Component
public class WebSocketConfig {
    @Bean
    public ServerEndpointExporter serverEndpointExporter() {
        return new ServerEndpointExporter();
    }
}

3.3編寫WebSocket類

package com.xiong.sell.service;

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
import java.util.concurrent.CopyOnWriteArraySet;


@Component
@ServerEndpoint("/webSocket")
@Slf4j
public class WebSocket {

    private Session session;

    //concurrent包的線程安全Set,用來存放每個客戶端對應的MyWebSocket對象。若要實現服務端與單一客戶端通信的話,可以使用Map來存放,其中Key可以為用戶標識
    private static CopyOnWriteArraySet<WebSocket> webSocketSet = new CopyOnWriteArraySet<>();

    /**
     * 連接建立成功調用的方法
     * @param session  可選的參數。session為與某個客戶端的連接會話,需要通過它來給客戶端發送數據
     */
    @OnOpen
    public void onOpen(Session session) {
        this.session = session;
        webSocketSet.add(this);
        log.info("【websocket消息】有新的連接, 總數:{}", webSocketSet.size());
    }

    /**
     * 關閉連接調用方法
     */
    @OnClose
    public void onClose() {
        webSocketSet.remove(this);
        log.info("【websocket消息】連接斷開, 總數:{}", webSocketSet.size());
    }

    /**
     * 收到客戶端消息后調用的方法
     * @param message 客戶端發送過來的消息
     */
    @OnMessage
    public void onMessage(String message) {
        log.info("【websocket消息】收到客戶端發來的消息:{}", message);
    }

    /**
     * 自定義的方法,群發參數
     * @param message 群發的內容
     */
    public void sendMessage(String message) {
        for (WebSocket webSocket: webSocketSet) {
            log.info("【websocket消息】廣播消息, message={}", message);
            try {
                webSocket.session.getBasicRemote().sendText(message);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

4.測試截圖

 

 


免責聲明!

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



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