springboot框架集成websocket依賴實現物聯網設備、前端網頁實時通信!

需求:
最近在對接一個物聯網里設備,他的通信方式是 websocket 。所以我需要在 springboot框架中集成websocket 依賴,從而實現與設備實時通信!
框架:springboot2.7
java版本:java8
好了,還是直接上代碼
第一步:引入依賴

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

第二步寫配置:

package com.agentai.base.config;import com.agentai.base.yumou.webSocket.YuMouDeviceWebSocketHandler;
import org.springframework.context.annotation.Bean;
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;
import org.springframework.web.socket.server.standard.ServletServerContainerFactoryBean;/*** WebSocket配置類* 負責配置WebSocket服務器和注冊WebSocket處理器*/
@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {@Overridepublic void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {// 注冊WebSocket處理器,// 允許所有來源的跨域請求registry.addHandler(deviceWebSocketHandler(), "/linker-dev").setAllowedOrigins("*");}@Beanpublic YuMouDeviceWebSocketHandler deviceWebSocketHandler() {return new YuMouDeviceWebSocketHandler();}@Beanpublic ServletServerContainerFactoryBean createWebSocketContainer() {ServletServerContainerFactoryBean container = new ServletServerContainerFactoryBean();// 設置消息緩沖區大小container.setMaxTextMessageBufferSize(8192);container.setMaxBinaryMessageBufferSize(8192);// 設置會話超時時間(毫秒)container.setMaxSessionIdleTimeout(60000L);return container;}
}

第三方:WebSocket會話管理器

package com.agentai.base.yumou.webSocket;import lombok.extern.slf4j.Slf4j;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;import java.io.IOException;
import java.time.Instant;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;/*** WebSocket會話管理器* 負責管理所有WebSocket會話,包括會話狀態跟蹤、心跳檢測和清理過期會話*/
@Slf4j
public class WebSocketSessionManager {// 心跳超時限制(毫秒)private static final long HEARTBEAT_TIMEOUT = 30000;// 心跳檢查間隔(毫秒)private static final long HEARTBEAT_CHECK_INTERVAL = 10000;// 心跳消息內容private static final String HEARTBEAT_MESSAGE = "{\"type\":\"ping\"}";// 會話信息,包含WebSocket會話和最后活動時間private static class SessionInfo {WebSocketSession session;long lastActiveTime;SessionInfo(WebSocketSession session) {this.session = session;this.lastActiveTime = Instant.now().toEpochMilli();}void updateLastActiveTime() {this.lastActiveTime = Instant.now().toEpochMilli();}}// 保存所有會話信息private final Map<String, SessionInfo> sessions = new ConcurrentHashMap<>();private final ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();public WebSocketSessionManager() {// 啟動心跳檢查任務scheduler.scheduleAtFixedRate(this::checkHeartbeats,HEARTBEAT_CHECK_INTERVAL, HEARTBEAT_CHECK_INTERVAL, TimeUnit.MILLISECONDS);}/*** 添加新的會話* @param session 新的WebSocket會話*/public void addSession(WebSocketSession session) {sessions.put(session.getId(), new SessionInfo(session));log.info("新會話已添加: {}", session.getId());}/*** 移除會話* @param sessionId 會話ID*/public void removeSession(String sessionId) {sessions.remove(sessionId);log.info("會話已移除: {}", sessionId);}/*** 更新會話最后活動時間* @param sessionId 會話ID*/public void updateSessionActivity(String sessionId) {SessionInfo info = sessions.get(sessionId);if (info != null) {info.updateLastActiveTime();}}/*** 發送消息到指定會話* @param sessionId 會話ID* @param message 消息內容* @return 是否發送成功*/public boolean sendMessage(String sessionId, String message) {SessionInfo info = sessions.get(sessionId);if (info != null && info.session.isOpen()) {try {info.session.sendMessage(new TextMessage(message));return true;} catch (IOException e) {log.error("發送消息到會話[{}]失敗: {}", sessionId, e.getMessage());}}return false;}/*** 廣播消息到所有會話* @param message 消息內容*/public void broadcastMessage(String message) {sessions.forEach((sessionId, info) -> {if (info.session.isOpen()) {try {info.session.sendMessage(new TextMessage(message));} catch (IOException e) {log.error("廣播消息到會話[{}]失敗: {}", sessionId, e.getMessage());}}});}/*** 檢查心跳并清理過期會話*/private void checkHeartbeats() {long now = Instant.now().toEpochMilli();sessions.forEach((sessionId, info) -> {if (now - info.lastActiveTime > HEARTBEAT_TIMEOUT) {try {// 發送心跳消息info.session.sendMessage(new TextMessage(HEARTBEAT_MESSAGE));log.debug("發送心跳到會話: {}", sessionId);} catch (IOException e) {// 如果發送失敗,關閉并移除會話log.warn("會話[{}]心跳檢測失敗,關閉會話: {}", sessionId, e.getMessage());try {info.session.close();} catch (IOException ex) {log.error("關閉會話[{}]失敗: {}", sessionId, ex.getMessage());}removeSession(sessionId);}}});}/*** 關閉會話管理器*/public void shutdown() {scheduler.shutdown();sessions.forEach((sessionId, info) -> {try {info.session.close();} catch (IOException e) {log.error("關閉會話[{}]失敗: {}", sessionId, e.getMessage());}});sessions.clear();}
}

第四步:設備WebSocket處理器

package com.agentai.base.yumou.webSocket;import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.socket.BinaryMessage;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;
/*** 設備WebSocket處理器* 負責處理設備的WebSocket連接、消息接收和斷開連接*/
@Slf4j
public class YuMouDeviceWebSocketHandler extends TextWebSocketHandler {private final WebSocketSessionManager sessionManager;// 構造函數,初始化會話管理器public YuMouDeviceWebSocketHandler() {this.sessionManager = new WebSocketSessionManager();}/*** WebSocket連接建立后的處理* @param session WebSocket會話*/@Overridepublic void afterConnectionEstablished(WebSocketSession session) {// 將新會話添加到會話管理器String sessionId = session.getId();sessionManager.addSession(session);log.info("WebSocket連接已建立: {}", sessionId);}@AutowiredYuMouService yuMouService;/*** 處理接收到的文本消息* @param session 當前會話* @param message 接收到的文本消息*/@Overrideprotected void handleTextMessage(WebSocketSession session, TextMessage message) {String payload = message.getPayload();String sessionId = session.getId();try {// 更新會話的活動時間sessionManager.updateSessionActivity(sessionId);log.info("接收到設備[{}]的文本消息: {}", sessionId, payload);JSONObject jsonObject = JSONObject.parseObject(payload);log.info("數據:", jsonObject );// 處理其他業務消息// TODO: 添加具體的業務消息處理邏輯} catch (Exception e) {log.error("處理設備[{}]消息時發生錯誤: {}", sessionId, e.getMessage());}}/*** 處理接收到的二進制消息* @param session 當前會話* @param message 接收到的二進制消息*/@Overrideprotected void handleBinaryMessage(WebSocketSession session, BinaryMessage message) {byte[] payload = message.getPayload().array();String sessionId = session.getId();log.info("接收到設備[{}]的二進制消息,長度: {} 字節", sessionId, payload.length);// 目前只打印消息長度,可以根據需求處理二進制數據// TODO: 添加二進制消息處理邏輯}/*** 處理傳輸錯誤* @param session 當前會話* @param exception 錯誤異常*/@Overridepublic void handleTransportError(WebSocketSession session, Throwable exception) {String sessionId = session.getId();log.error("設備[{}]連接傳輸錯誤: {}", sessionId, exception.getMessage());}/*** WebSocket連接關閉后的處理* @param session 當前會話* @param status 關閉狀態*/@Overridepublic void afterConnectionClosed(WebSocketSession session, CloseStatus status) {String sessionId = session.getId();sessionManager.removeSession(sessionId);log.info("設備[{}]WebSocket連接已關閉,狀態碼: {}", sessionId, status.getCode());}/*** 發送消息到指定會話* @param sessionId 會話ID* @param message 消息內容* @return 是否發送成功*/public boolean sendMessage(String sessionId, String message) {return sessionManager.sendMessage(sessionId, message);}/*** 廣播消息到所有連接的會話* @param message 消息內容*/public void broadcastMessage(String message) {sessionManager.broadcastMessage(message);}/*** 關閉WebSocket處理器,清理資源*/public void shutdown() {sessionManager.shutdown();}
}

在這里插入圖片描述

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/78888.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/78888.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/78888.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

第八天 開始Unity Shader的學習之Blinn-Phong光照模型

Unity Shader的學習筆記 第八天 開始Unity Shader的學習之Blinn-Phong光照模型 文章目錄 Unity Shader的學習筆記前言一、Blinn-Phong光照模型①計算高光反射部分效果展示 二、召喚神龍:使用Unity內置的函數總結 前言 今天我們編寫另一種高光反射的實現方法 – Blinn光照模型…

React八案例上

代碼下載 技術棧&#xff1a; React 核心庫&#xff1a;react、react-dom、react-router-dom腳手架&#xff1a;create-react-app數據請求&#xff1a;axiosUI組件庫&#xff1a; antd-mobile其他組件庫&#xff1a; react-virtualized、formikyup、react-spring 等百度地圖A…

線代[13]|線性代數題37道以及數學分析題3道(多圖預警)

博主首次發布于CSDN&#xff0c;禁止轉載&#xff01;&#xff08;CSDN&#xff1a;漢密士2025&#xff09; 文章目錄 一、緣起&#xff5c;《俗說矩陣》課程目錄照片存檔&#xff5c;線性代數學習脈絡&#xff5c;線代習題集封面存檔&#xff5c;未來——我與線性代數的糾纏 二…

OpenCV 圖形API(24)圖像濾波-----雙邊濾波函數bilateralFilter()

操作系統&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 編程語言&#xff1a;C11 算法描述 應用雙邊濾波到圖像。 該函數對輸入圖像應用雙邊濾波&#xff0c;如 http://www.dai.ed.ac.uk/CVonline/LOCAL_COPIES/MANDUCHI1/Bilateral_Fil…

AI與5G的融合:如何實現更快速、更智能的物聯網應用?

引言 AI和5G的結合&#xff0c;正在加速物聯網&#xff08;IoT&#xff09;應用的發展&#xff0c;讓萬物互聯變得更加智能、高效。5G提供超高速率、低時延和海量連接的網絡能力&#xff0c;而AI則賦予物聯網設備更強的數據分析、預測和自動決策能力。當AI與5G融合&#xff0c;…

在ArcGIS Pro中將柵格NoData值修改為特定值

目錄 問題如下&#xff1a;柵格文件中NoData值為65535&#xff0c;要將該NoData值修改為-9999 步驟一&#xff1a;使用柵格計算器&#xff08;Raster Calculator&#xff09;輸出具有新NoData值的柵格文件 步驟二&#xff1a;輸出修改值后的柵格文件&#xff08;Export Rast…

藍牙連接hci 命令和事件的交互

參考&#xff1a;在HCI層看藍牙的連接過程_hci 獲取藍牙pin碼-CSDN博客 我這邊查看的是core 5.2 一、數據交互流程 1、ACL連接建立后的可選流程 參考藍牙core5.2: vol2 --> PartF --> 4 1.1 AUTHENTICATION REQUESTED Authentication can be explicitly executed at …

【計算機網絡實踐】(十二)大學校園網綜合項目設計

本系列包含&#xff1a; &#xff08;一&#xff09;以太網幀分析與網際互聯協議報文結構分析 &#xff08;二&#xff09;地址解析協議分析與傳輸控制協議特性分析 &#xff08;三&#xff09;交換機的基本操作、配置、 虛擬局域網配置和應用 &#xff08;四&#xff09;交…

制造企業數據治理體系搭建與業務賦能實踐

當下制造企業正面臨著前所未有的機遇與挑戰&#xff0c;從多環節業務協同的復雜性&#xff0c;到海量數據資源的沉睡與孤島化&#xff1b;從個性化定制需求的爆發&#xff0c;到供應鏈效率優化的迫切性——如何通過數據治理將“數據包袱”轉化為“數據資產”&#xff0c;已成為…

python高級編程一(生成器與高級編程)

@TOC 生成器 生成器使用 通過列表?成式,我們可以直接創建?個列表。但是,受到內存限制,列表容量肯定是有限的。?且,創建?個包含100萬個元素的列表,不僅占?很?的存儲空間,如果我們僅僅需要訪問前??個元素,那后?絕?多數元素占 ?的空間都??浪費了。所以,如果…

智能指針之設計模式2

前面介紹了工廠模式控制了智能指針和資源對象的創建過程&#xff0c;現在介紹一下智能指針是如何利用代理模式來實現“類指針&#xff08;like-pointer&#xff09;”的功能&#xff0c;并控制資源對象的銷毀過程的。 2、代理模式 代理模式是為其它對象提供一種代理以控制對這…

探索R語言:在線學習資源匯總

一、收集關于特定R主題的問題和答案&#xff08;Q&A&#xff09; 1. Stack overflow Empowering the world to develop technology through collective knowledge – Stack Overflowhttps://stackoverflow.co/ 二、Rstudio工具欄help Rstudio中有個Cheat sheet&#xf…

《C語言中以數組作為參數的探討》

&#x1f680;個人主頁&#xff1a;BabyZZの秘密日記 &#x1f4d6;收入專欄&#xff1a;C語言 &#x1f30d;文章目入 一、數組作為參數的傳遞機制二、數組參數的聲明方式&#xff08;一&#xff09;省略數組大小&#xff08;二&#xff09;指定數組大小&#xff08;三&#x…

深入解析區塊鏈技術:原理、應用與未來展望

1 區塊鏈技術原理 1.1 基本概念 區塊鏈本質上是一個分布式賬本&#xff0c;它由一系列按照時間順序排列的數據塊組成&#xff0c;每個數據塊包含了一定時間內的交易信息。這些數據塊通過密碼學技術相互鏈接&#xff0c;形成一個不可篡改的鏈條。其核心特點包括去中心化、不可篡…

selenium快速入門

一、操作瀏覽器 from selenium import webdriver from selenium.webdriver.chrome.options import Options from selenium.webdriver.chrome.service import Service from selenium.webdriver.common.by import By# 設置選項 q1 Options() q1.add_argument("--no-sandbo…

面試如何應用大模型

在面試中,如果被問及如何應用大模型,尤其是面向政務、國有企業或大型傳統企業的數字化轉型場景,你可以從以下幾個角度進行思考和回答: 1. 確定應用大模型的目標與痛點 首先,明確應用大模型的業務目標,并結合企業的實際需求分析可能面臨的痛點。這些企業通常會關注如何提…

嵌入式常見概念的介紹

目錄 一、MCU、MPU、ARM &#xff08;一&#xff09;MCU&#xff08;微控制器&#xff09; &#xff08;二&#xff09;MPU&#xff08;微處理器&#xff09; &#xff08;三&#xff09;ARM&#xff08;架構&#xff09; 二、DSP &#xff08;一&#xff09;數字信號處理…

深度強化學習(DRL)框架與多目標調度優化詳解

深度強化學習&#xff08;DRL&#xff09;框架與多目標調度優化詳解 &#xff08;截至2025年4月&#xff0c;結合最新研究進展&#xff09; 一、DRL主流框架及核心算法 通用DRL框架 Ray RLlib&#xff1a;支持分布式訓練&#xff0c;集成PPO、A3C、DQN等算法&#xff0c;適用于…

centos 安裝python3.9.9

這里寫自定義目錄標題 安裝編譯依賴 sudo yum -y groupinstall "Development Tools" sudo yum -y install openssl-devel bzip2-devel libffi-devel wget zlib-devel yum install zlib-devel bzip2-devel openssl-devel ncurses-devel sqlite-devel readline-devel …

【動態規劃】深入動態規劃:背包問題

文章目錄 前言01背包例題一、01背包二、分割等和子集三、目標和四、最后一塊石頭的重量|| 完全背包例題一、完全背包二、 零錢兌換三、零錢兌換||四、完全平方數 前言 什么是背包問題&#xff0c;怎么解決算法中的背包問題呢&#xff1f; 背包問題 (Knapsack problem) 是?種組…