最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

在SpringBoot中實(shí)現(xiàn)WebSocket會(huì)話管理的方案

 更新時(shí)間:2023年11月24日 08:39:46   作者:一只愛(ài)擼貓的程序猿  
在構(gòu)建實(shí)時(shí)通信應(yīng)用時(shí),WebSocket 無(wú)疑是一個(gè)強(qiáng)大的工具,SpringBoot提供了對(duì)WebSocket的支持,本文旨在探討如何在 Spring Boot 應(yīng)用中實(shí)現(xiàn) WebSocket 會(huì)話管理,我們將通過(guò)一個(gè)模擬的場(chǎng)景一步步展開(kāi)討論,需要的朋友可以參考下

場(chǎng)景設(shè)定

假設(shè)我們正在開(kāi)發(fā)一個(gè)在線聊天應(yīng)用,該應(yīng)用需要實(shí)現(xiàn)以下功能:

  • 用戶可以通過(guò) WebSocket 實(shí)時(shí)發(fā)送和接收消息。
  • 系統(tǒng)需要跟蹤用戶的會(huì)話狀態(tài),以便在用戶重新連接時(shí)恢復(fù)狀態(tài)。
  • 為了提高效率和安全性,我們需要監(jiān)控空閑連接并及時(shí)關(guān)閉它們。

基于這個(gè)場(chǎng)景,我們將探討四種實(shí)現(xiàn) WebSocket 會(huì)話管理的策略:

1. 使用現(xiàn)有的會(huì)話標(biāo)識(shí)符

一種常見(jiàn)的做法是利用 HTTP 會(huì)話(例如,通過(guò) cookies)來(lái)管理 WebSocket 會(huì)話。

實(shí)現(xiàn)方法

  • 在 WebSocket 握手階段,從 HTTP 請(qǐng)求中提取會(huì)話標(biāo)識(shí)符。
  • 將 WebSocket 會(huì)話與提取的會(huì)話標(biāo)識(shí)符關(guān)聯(lián)。
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.http.server.ServletServerHttpRequest;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.server.support.HttpSessionHandshakeInterceptor;

import javax.servlet.http.HttpSession;
import java.util.Map;

public class MyHandshakeInterceptor extends HttpSessionHandshakeInterceptor {
    
    @Override
    public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception {
        if (request instanceof ServletServerHttpRequest) {
            ServletServerHttpRequest servletRequest = (ServletServerHttpRequest) request;
            HttpSession session = servletRequest.getServletRequest().getSession();
            attributes.put("HTTP_SESSION_ID", session.getId());
        }
        return super.beforeHandshake(request, response, wsHandler, attributes);
    }
}

這個(gè)攔截器需要在 WebSocket 的配置類中注冊(cè)。例如,在 WebSocketConfig 類中,你可以這樣注冊(cè)攔截器:

import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;

@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {

    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
        registry.addHandler(new MyWebSocketHandler(), "/ws")
                .addInterceptors(new MyHandshakeInterceptor())
                .setAllowedOrigins("*");
        // 你也可以添加 .withSockJS() 如果你需要SockJS支持
    }

    // ...其他配置...
}

2. 自定義協(xié)議消息

另一種方法是在 WebSocket 連接中定義自己的消息格式,包含會(huì)話管理信息。

實(shí)現(xiàn)方法

  • 定義消息格式(如 JSON),包含會(huì)話信息。
  • 在連接建立后,通過(guò) WebSocket 發(fā)送和接收這些自定義消息。
@Controller
public class WebSocketController {
    
    @Autowired
    private WebSocketSessionManager sessionManager;

    @MessageMapping("/sendMessage")
    public void handleSendMessage(ChatMessage message, SimpMessageHeaderAccessor headerAccessor) {
        String sessionId = (String) headerAccessor.getSessionAttributes().get("HTTP_SESSION_ID");
        // 使用 sessionId 處理消息
        // 可以通過(guò) sessionManager 獲取用戶信息
    }

    // ...其他消息處理方法...
}

3. 連接映射

將每個(gè) WebSocket 連接映射到特定的用戶會(huì)話。

實(shí)現(xiàn)方法

  • 在連接建立時(shí),從 WebSocket 握手信息中獲取用戶身份。
  • 維護(hù)一個(gè)映射,關(guān)聯(lián) WebSocket 會(huì)話 ID 和用戶會(huì)話。
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler; 
import java.util.Iterator; 
import org.springframework.stereotype.Component;
import java.util.concurrent.ConcurrentHashMap;
import java.util.Map;

@Component
public class WebSocketSessionManager extends TextWebSocketHandler {

    @Autowired
    private WebSocketHandler webSocketHandler;
    
    private Map<String, String> sessionMap = new ConcurrentHashMap<>();
    private Map<String, Long> lastActiveTimeMap = new ConcurrentHashMap<>();

    public void registerSession(String websocketSessionId, String userSessionId) {
        sessionMap.put(websocketSessionId, userSessionId);
        lastActiveTimeMap.put(websocketSessionId, System.currentTimeMillis());
    }

    public String getUserSessionId(String websocketSessionId) {
        return sessionMap.get(websocketSessionId);
    }

    public void updateLastActiveTime(String websocketSessionId) {
        lastActiveTimeMap.put(websocketSessionId, System.currentTimeMillis());
    }

    public Long getLastActiveTime(String websocketSessionId) {
        return lastActiveTimeMap.get(websocketSessionId);
    }

    public void checkAndCloseInactiveSessions(long timeout) {
        long currentTime = System.currentTimeMillis();
        lastActiveTimeMap.entrySet().removeIf(entry -> {
            String sessionId = entry.getKey();
            long lastActiveTime = entry.getValue();

            if (currentTime - lastActiveTime > timeout) {
                closeSession(sessionId);  // 關(guān)閉會(huì)話
                sessionMap.remove(sessionId);  // 從用戶會(huì)話映射中移除
                return true;  // 從活躍時(shí)間映射中移除
            }
            return false;
        });
    }

    private void closeSession(String websocketSessionId) {
        // 邏輯來(lái)關(guān)閉 WebSocket 會(huì)話
        // 可能需要與 webSocketHandler 交互
    }
    
    public void unregisterSession(String websocketSessionId) {
        sessionMap.remove(websocketSessionId);
    }
    // 可以添加注銷會(huì)話的方法等
}

4. 心跳和超時(shí)機(jī)制

實(shí)現(xiàn)心跳消息和超時(shí)機(jī)制,以管理會(huì)話的生命周期。

實(shí)現(xiàn)方法

  • 客戶端定時(shí)發(fā)送心跳消息。
  • 服務(wù)端監(jiān)聽(tīng)這些消息,并實(shí)現(xiàn)超時(shí)邏輯。
function sendHeartbeat() {
    if (stompClient && stompClient.connected) {
        stompClient.send("/app/heartbeat", {}, JSON.stringify({ timestamp: new Date() }));
    }
}
setInterval(sendHeartbeat, 10000); // 每10秒發(fā)送一次心跳
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.stereotype.Controller;

@Controller
public class HeartbeatController {

    @Autowired
    private WebSocketSessionManager sessionManager;

    @MessageMapping("/heartbeat")
    public void handleHeartbeat(HeartbeatMessage message, SimpMessageHeaderAccessor headerAccessor) {
        String websocketSessionId = headerAccessor.getSessionId();
        sessionManager.updateLastActiveTime(websocketSessionId);
        // 根據(jù)需要處理其他邏輯
    }
}

使用 Spring 的定時(shí)任務(wù)功能來(lái)定期執(zhí)行會(huì)話超時(shí)檢查,ScheduledTasks 類中的 checkInactiveWebSocketSessions 方法每5秒執(zhí)行一次,調(diào)用 WebSocketSessionManagercheckAndCloseInactiveSessions 方法來(lái)檢查和關(guān)閉超時(shí)的會(huì)話。

import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

@EnableScheduling
@Component
public class ScheduledTasks {

    @Autowired
    private WebSocketSessionManager sessionManager;

    // 定義超時(shí)閾值,例如30分鐘
    private static final long TIMEOUT_THRESHOLD = 30 * 60 * 1000;

    @Scheduled(fixedRate = 5000) // 每5秒執(zhí)行一次
    public void checkInactiveWebSocketSessions() {
        sessionManager.checkAndCloseInactiveSessions(TIMEOUT_THRESHOLD);
    }
}

補(bǔ)充:在 WebSocket 連接關(guān)閉或用戶注銷時(shí),可以調(diào)用 unregisterSession 方法來(lái)清理會(huì)話信息。當(dāng) WebSocket 連接關(guān)閉時(shí),afterConnectionClosed 方法會(huì)被調(diào)用,這時(shí)我們可以通過(guò) sessionManager 移除對(duì)應(yīng)的會(huì)話信息。

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

public class MyWebSocketHandler extends TextWebSocketHandler {

    @Autowired
    private WebSocketSessionManager sessionManager;

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        String websocketSessionId = session.getId();
        sessionManager.unregisterSession(websocketSessionId);
        // 進(jìn)行其他清理工作
    }

    // 實(shí)現(xiàn)其他必要的方法
}

總結(jié)

實(shí)現(xiàn) WebSocket 會(huì)話管理需要綜合考慮應(yīng)用的需求和架構(gòu)特點(diǎn)。Spring Boot 提供了實(shí)現(xiàn)這些功能的強(qiáng)大支持,但正確地應(yīng)用這些工具和策略是成功的關(guān)鍵。通過(guò)本文的討論,我們看到了如何在一個(gè)實(shí)際場(chǎng)景中一步步地思考和實(shí)現(xiàn)有效的 WebSocket 會(huì)話管理。

以上就是在SpringBoot中實(shí)現(xiàn)WebSocket會(huì)話管理的方案的詳細(xì)內(nèi)容,更多關(guān)于SpringBoot實(shí)現(xiàn)WebSocket會(huì)話的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 一文帶你徹底了解MySQL事務(wù)機(jī)制

    一文帶你徹底了解MySQL事務(wù)機(jī)制

    一個(gè)事情由n個(gè)單元組成,這n個(gè)單元在執(zhí)行過(guò)程中,要么同時(shí)成功,要么同時(shí)失敗,這就把n個(gè)單元放在了一個(gè)事務(wù)之中,這篇文章主要給大家詳細(xì)介紹MySQL的事務(wù)機(jī)制,感興趣的同學(xué)歡迎閱讀本文
    2023-06-06
  • 淺談MySQL分頁(yè)Limit的性能問(wèn)題

    淺談MySQL分頁(yè)Limit的性能問(wèn)題

    這篇文章主要介紹了淺談MySQL分頁(yè)Limit的性能問(wèn)題,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-08-08
  • MySQL數(shù)據(jù)誤刪恢復(fù)的完整指南

    MySQL數(shù)據(jù)誤刪恢復(fù)的完整指南

    在數(shù)據(jù)庫(kù)運(yùn)維中,drop table 誤刪表、delete 誤刪數(shù)據(jù)是最讓人崩潰的場(chǎng)景之一,一旦操作失誤,輕則業(yè)務(wù)中斷,重則數(shù)據(jù)永久丟失,本文結(jié)合實(shí)戰(zhàn)場(chǎng)景,詳細(xì)拆解兩種核心誤操作的恢復(fù)流程,需要的朋友可以參考下
    2026-02-02
  • Linux下mysql異地自動(dòng)備份的方法

    Linux下mysql異地自動(dòng)備份的方法

    這篇文章主要介紹了Linux下mysql異地自動(dòng)備份的方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-06-06
  • MySQL select、insert、update批量操作語(yǔ)句代碼實(shí)例

    MySQL select、insert、update批量操作語(yǔ)句代碼實(shí)例

    這篇文章主要介紹了MySQL select、insert、update批量操作語(yǔ)句代碼實(shí)例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-03-03
  • Mysql數(shù)據(jù)庫(kù)設(shè)計(jì)三范式實(shí)例解析

    Mysql數(shù)據(jù)庫(kù)設(shè)計(jì)三范式實(shí)例解析

    這篇文章主要介紹了Mysql數(shù)據(jù)庫(kù)設(shè)計(jì)三范式實(shí)例解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-04-04
  • mysql 8.0.22 zip壓縮包版(免安裝)下載、安裝配置步驟詳解

    mysql 8.0.22 zip壓縮包版(免安裝)下載、安裝配置步驟詳解

    這篇文章主要介紹了mysql 8.0.22 zip壓縮包版(免安裝)下載、安裝配置步驟詳解,本文分步驟通過(guò)圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-12-12
  • SQL 聚合、分組和排序

    SQL 聚合、分組和排序

    這篇文章主要介紹了SQL 聚合、分組和排序,文章圍繞SQL 聚合、分組、排序的相關(guān)資料展開(kāi)具體內(nèi)容,需要的朋友可以參考一下
    2021-11-11
  • mysqldump你可能不知道的參數(shù)

    mysqldump你可能不知道的參數(shù)

    這篇文章主要介紹了mysqldump你可能不知道的參數(shù),幫助大家更好的理解和使用MySQL,感興趣的朋友可以了解下
    2020-11-11
  • MySQL數(shù)據(jù)庫(kù)約束詳解

    MySQL數(shù)據(jù)庫(kù)約束詳解

    mysql常見(jiàn)約束有:1、非空約束“not?null”;2、唯一性約束“unique”;3、主鍵約束“primary?key”;4、外鍵約束“foreign?key”;5、默認(rèn)值約束“Default”等等。
    2022-10-10

最新評(píng)論

大邑县| 禹州市| 永善县| 酒泉市| 葵青区| 中宁县| 云和县| 彰化市| 乡城县| 巴南区| 宁安市| 日土县| 内黄县| 镇坪县| 荣成市| 元谋县| 海宁市| 富川| 五原县| 西乡县| 建宁县| 迁安市| 邯郸市| 广平县| 敖汉旗| 铁岭市| 霞浦县| 荃湾区| 东兰县| 东莞市| 荣成市| 铜山县| 湘西| 周至县| 阿拉善盟| 寿宁县| 浦城县| 靖宇县| 江永县| 香港| 麻城市|