WebSocket

launch發表於2024-05-21

WebSocket 是基於 TCP 的一種新的網路協議。全雙工通訊,就是隻需要建立一次握手,即可瀏覽器和伺服器雙向資料傳輸

HTTP協議和WebSocket協議對比:
HTTP是短連線
WebSocket是長連線
HTTP通訊是單向的,基於請求響應模式
WebSocket支援雙向通訊
HTTP和WebSocket底層都是TCP連線

String json = JSON.toJSONString(map);
即可將map轉化為json字串
然後呼叫websocket中的方法sendToAllClient(json)
即可傳送到前端,推送訊息

應用場景:彈幕,網頁聊天視窗、體育實況更新、股票基金報價實時更新
個人理解:非同步不重新整理

匯入依賴

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

WebSocketServer類
這跟controller很像,都是透過路徑匹配

package com.sky.websocket;

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.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

/**
 * WebSocket服務
 */
@Component
@ServerEndpoint("/ws/{sid}")
public class WebSocketServer {

    //存放會話物件
    private static Map<String, Session> sessionMap = new HashMap();

    /**
     * 連線建立成功呼叫的方法
     */
    @OnOpen
    public void onOpen(Session session, @PathParam("sid") String sid) {
        System.out.println("客戶端:" + sid + "建立連線");
        sessionMap.put(sid, session);
    }

    /**
     * 收到客戶端訊息後呼叫的方法
     *
     * @param message 客戶端傳送過來的訊息
     */
    @OnMessage
    public void onMessage(String message, @PathParam("sid") String sid) {
        System.out.println("收到來自客戶端:" + sid + "的資訊:" + message);
    }

    /**
     * 連線關閉呼叫的方法
     *
     * @param sid
     */
    @OnClose
    public void onClose(@PathParam("sid") String sid) {
        System.out.println("連線斷開:" + sid);
        sessionMap.remove(sid);
    }

    /**
     * 群發
     *
     * @param message
     */
    public void sendToAllClient(String message) {
        Collection<Session> sessions = sessionMap.values();
        for (Session session : sessions) {
            try {
                //伺服器向客戶端傳送訊息
                session.getBasicRemote().sendText(message);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

}

WebSocketconfig

package com.sky.config;

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

/**
 * WebSocket配置類,用於註冊WebSocket的Bean
 */
@Configuration
public class WebSocketConfiguration {

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

}

為了測試效果,又定義了一個定時任務類來測試這個WebSocket

package com.sky.task;

import com.sky.websocket.WebSocketServer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

@Component
public class WebSocketTask {
    @Autowired
    private WebSocketServer webSocketServer;

    /**
     * 透過WebSocket每隔5秒向客戶端傳送訊息
     */
    @Scheduled(cron = "0/5 * * * * ?")
    public void sendMessageToClient() {
        webSocketServer.sendToAllClient("這是來自服務端的訊息:" + DateTimeFormatter.ofPattern("HH:mm:ss").format(LocalDateTime.now()));
    }
}

相關文章