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.mzph.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) 是⼀种组…