spring-boot集成websocket
引入Maven依赖包
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId><version>跟随spingboot版本</version>
</dependency>
后端代码
/*** 开启WebSocket支持*/
@Configuration
public class WebSocketConfig {@Beanpublic ServerEndpointExporter serverEndpointExporter() {return new ServerEndpointExporter();}
}@Component
@Slf4j
@ServerEndpoint("/demand/task/webSocket/{taskId}") // 前端请求URL
public class TaskWebSocketServer {/*** 保存每个需求任务对应的服务对象*/private static CopyOnWriteArraySet<TaskWebSocketServer> TASK_CACHE = new CopyOnWriteArraySet<>();private Session session;private Long taskId;private static DemandTestTaskService demandTestTaskService;/*** 注入依赖业务处理服务*/@Autowiredpublic void setSunPurchasePayService(DemandTestTaskService demandTestTaskService) {this.demandTestTaskService = demandTestTaskService;}public List<TaskWebSocketServer> getTaskSocketServerList(){List<TaskWebSocketServer> serverList = new ArrayList<>(TASK_CACHE.size());TASK_CACHE.forEach(server -> serverList.add(server));return serverList;}public Long getTaskId(){return taskId;}public boolean userExist(String userId, String deviceId){if (CollectionUtils.isEmpty(pulsarList)){log.info("任务列表为空,请先创建任务 userId:{} deviceId:{}", userId, deviceId);return false;}for (DemandTaskPulsarBO pulsarBO: pulsarList){if (Long.valueOf(userId).equals(pulsarBO.getUserId())){return true;}if (deviceId.equals(pulsarBO.getDeviceId())){return true;}}return false;}/*** 连接建立成功调用的方法*/@OnOpenpublic void onOpen(Session session, @PathParam(value = "taskId") Long taskId) {if (TASK_CACHE.size() > 10){throw new BusinessException(CodeEnum.FAIL.getCode(), "测试任务已达到最大上限10个,请稍后重试");}if (this.taskId != null && this.taskId.equals(taskId)){log.info("web socket reconnection taskId:{}", taskId);}this.taskId = taskId;// TODO 补偿你的业务逻辑// 设置会话超时时间 30 * 60 * 1000session.setMaxIdleTimeout(1800000L);this.session = session;TASK_CACHE.add(this);try {session.getBasicRemote().sendText("connect success. taskId=" + taskId);log.info("web socket connect success taskId:{} pulsarList:{}", taskId, JacksonUtil.toJSONString(pulsarBOS));} catch (IOException e) {log.error("websocket IO Exception");}}/*** 连接关闭调用的方法*/@OnClosepublic void onClose() {try{TASK_CACHE.remove(this);// TODO 补充关闭连接的逻辑}catch (Exception e){log.error("web socket closed error taskId:{}", taskId, e);}}/*** 实现服务器主动推送*/public void sendMessage(String message) throws IOException {// 高并发情况下,使用websocket出现报错的问题synchronized (this.session){this.session.getBasicRemote().sendText(message);}}
}
前端代码
<script setup>
import { reactive, toRefs, onBeforeUnmount, onMounted, getCurrentInstance } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
const Env = import.meta.env.VITE_API_ENV
const { proxy } = getCurrentInstance()
const { $axios, $store } = proxylet ws = {}
let heartTime = null // 心跳定时器实例
let socketHeart = 0 // 心跳次数
let HeartTimeOut = 5000 // 心跳超时时间
let socketError = 0 // 错误次数
const _data = reactive({tableHeight: '488px',demandId: '',pointData: {},deviceId: '',userId: '',isContent: false,list: [],taskId: '',testData: {},isHandStop: false,testList: [],testAppKey: ''
})onMounted(() => {})const initWebSocket = taskId => {_data.isHandStop = falselet url = MakeWss(taskId)ws = new WebSocket(url)ws.onopen = function (e) {_data.isContent = trueconsole.log(e)}ws.onmessage = function (e) {console.log(e, e.data)if (e.data.indexOf('connect') == -1) {let dataList = JSON.parse(e.data)_data.list.push(dataList)changePointStatus(dataList)} else {resetHeart()}}ws.onerror = function (e) {console.log(e)reconnect()}ws.onclose = function (e) {console.log(e)_data.isContent = falseif (_data.isHandStop == false) {reconnect()}}
}// socket 重置心跳
const resetHeart = () => {socketHeart = 0socketError = 0clearInterval(heartTime)sendSocketHeart()
}// socket心跳发送
const sendSocketHeart = () => {heartTime = setInterval(() => {console.log('心跳发送:', socketHeart)ws.send(JSON.stringify({content: '',requestId: 'aa9872be-d5b9-478e-aba4-50527cd3ef32',type: 'heartbeat'}))socketHeart = socketHeart + 1}, HeartTimeOut)
}// socket重连
const reconnect = () => {if (socketError <= 2) {clearInterval(heartTime)initWebSocket(_data.taskId)socketError = socketError + 1console.log('socket重连', socketError)} else {console.log('重试次数已用完的逻辑', socketError)clearInterval(heartTime)}
}function stopTest() {_data.isHandStop = trueclearInterval(heartTime)ws.close()_data.isContent = false$axios.get(`/user/detail`, { demandId: _data.demandId, taskId: _data.taskId }).then(res => {if (res.success && res.data) {_data.pointData = res.data_data.testList = res.data.pointList}})
}
function clearTestList() {_data.list = []
}
function handleResize() {_data.tableHeight = document.documentElement.clientHeight - 230 + 'px'
}
window.addEventListener('resize', handleResize)
handleResize()onBeforeUnmount(() => {window.removeEventListener('resize', handleResize)
})
</script>
相关文章:
spring-boot集成websocket
引入Maven依赖包 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId><version>跟随spingboot版本</version> </dependency>后端代码 /*** 开启WebSocket支持*…...
【Python】【Flask】提交表单后报500错误
【背景】 日常用户使用的一个Online的基于Flask做的工具,今天忽然报错,看现象是点击表单提交按钮后发生错误。报500内部错误。 【分析】 用print步步为营接近root cause。 报错对应视图函数的展示部分正常执行。提交表单按钮后的内容全部没有正常执行。 提交表单用的方法是…...
Golang vs Java
目录 前言 一、语言背景与特性 二、性能与效率 三、生态系统与库支持 四、开发体验与工具支持 五、微服务架构设计中的对比 六、总结与建议 前言 在当今的软件开发世界中,选择合适的编程语言对于项目的成功至关重要。GoLang(也称为Golang&#x…...
HomePlug AV
目录 HomePlug AV的基本概念基本术语网络概念网络实例 HomePlug AV物理层(PHY)HomePlug AV OFDM收发器架构PHY的调制模式FC调制和ROBO调制物理层的特点OFDM频域/时域转换开窗/槽式OFDM信号和噪声PHY发送控制——信道自适应PHY帧格式(Symbol&a…...
【面试八股总结】超文本传输协议HTTP(二)
参考资料 :小林Coding、阿秀、代码随想录 一、HTTP缓存技术 将资源(如网页、图像、脚本等)的副本存储在客户端或中间代理服务器上,以便将来的请求可以直接从缓存中获取,而不必重新从服务器下载资源。这有助于减少网…...
SQL Server中视图使用子查询的性能影响与优化方案
在SQL Server中,视图(View)是一种虚拟的表,其内容由查询定义。在视图中,我们可以使用子查询来组合和呈现数据,这为数据呈现提供了灵活性,但同时也可能带来一些性能上的问题。本文将深入分析视图…...
Adaboost集成学习 | Matlab实现基于SVM-Adaboost支持向量机结合Adaboost集成学习时间序列预测(股票价格预测)
目录 效果一览基本介绍模型设计程序设计参考资料效果一览 基本介绍 Adaboost集成学习 | 基于SVM-Adaboost支持向量机结合Adaboost集成学习时间序列预测(股票价格预测)基于SVM(支持向量机)和AdaBoost集成学习的时间序列预测(如股票价格预测)是一种结合了两种强大机器学习算…...
Apache DolphinScheduler 【安装部署】
前言 今天来学习一下 DolphinScheduler ,这是一个任务调度工具,现在用的比较火爆。 1、安装部署 1.0、准备工作 1.0.1、集群规划 dolphinscheduler 比较吃内存,所以尽量给 master 节点多分配一点内存,桌面和虚拟机里能关的应用…...
【随笔】Git -- 高级命令(上篇)(六)
💌 所属专栏:【Git】 😀 作 者:我是夜阑的狗🐶 🚀 个人简介:一个正在努力学技术的CV工程师,专注基础和实战分享 ,欢迎咨询! 💖 欢迎大…...
java中Date类,SimpleDateFormat类和Calendar类
Date类 public Date() 创建一个Date对象,代表的是系统当前此刻的日期时间 public Date(long date) Constructs a Date object using the given milliseconds time value. 把时间毫秒值转变成Date日期对象 public void setTime(long date) Sets an existing Date ob…...
施耐德 PLC 控制系统 产品 + 软件总体介绍 2020
参考 2020.7 官方说明视频:https://www.bilibili.com/video/BV1Mi4y1G7Qc/ 总体说明 施耐德作为工业控制界巨头(公认的几大巨头:西门子、AB、施耐德),PLC 控制器产品线很庞大,涵盖了高中低的完整产品线&…...
UniApp 应用发布到苹果商店指南
🚀 想要让你的 UniApp 应用在苹果商店亮相吗?别着急,让我来带你一步步完成这个重要的任务吧!在这篇博客中,我将详细介绍如何将 UniApp 应用顺利发布到苹果商店,让你的应用跻身于苹果生态之中。 引言 &…...
KamaCoder 46. 携带研究材料(第六期模拟笔试)
题目描述 小明是一位科学家,他需要参加一场重要的国际科学大会,以展示自己的最新研究成果。他需要带一些研究材料,但是他的行李箱空间有限。这些研究材料包括实验设备、文献资料和实验样本等等,它们各自占据不同的空间࿰…...
MySQL的基本操作(超详细)
👨💻作者简介:👨🏻🎓告别,今天 📔高质量专栏 :☕java趣味之旅 📔(零基础)专栏:MSQL数据库 欢迎🙏点赞&…...
自动驾驶之心规划控制笔记
Search-based Path Planning Methods Path Finding Problem 一般来说指标有距离,耗费时间,能量,或者多目标。 左图是拓扑地图,蓝色的点就是顶点,绿色的线是连接关系。最后得到的是一个从哪里走的一个最优,并非精细解。 右图是栅格地图,这个搜索出来的是在相对分辨率比…...
Linux中部署Java jar 包 shell 脚本
Linux中部署Java jar 包 shell 脚本 #!/bin/bash set -e# 基础 # export JAVA_HOME/work/programs/jdk/jdk1.8.0_181 # export PATHPATH$PATH:$JAVA_HOME/bin # export CLASSPATH$JAVA_HOME/jre/lib/rt.jar:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jarDATE$(date %Y%m%d%…...
auto.js v1.4.4 实现自动打卡
一、使用场景 所在公司的打卡软件可以单独变成一个可以点击的APP,所以只需要实现以下步骤: 自动解锁屏幕返回主屏幕并打卡锁定屏幕需要的环境: 手机端下载并且安装 auto.js v4.1.1 PC端VS安装对应的插件学习资料 B站学习资料 对应 第三期&am…...
【Linux实验室】NFS、DHCP的搭建
NFS、DHCP的搭建 1、nfs服务搭建及测试什么是NFS?环境准备服务端机器安装nfs-utils和rpcbind包启动NFS服务创建/data/NFSdata目录,配置nfs文件启动服务挂载测试在服务端在共享目录下创建文件测试在客户端在共享目录下创建文件 2、dhcp服务搭建及测试什么…...
Samba 总是需要输入网络凭证
输入网络凭证: 用户名是 cat /etc/samba/smb.conf,查看 valid users mxw 为用户名。而不是其他账号名或者用户名,更不是登录计算机时的计算机名; 密码是 需要记住安装samba服务器时,自己设置的password࿱…...
图像处理_积分图
目录 1. 积分图算法介绍 2. 基本原理 2.1 构建积分图 2.2 使用积分图 3. 举个例子 1. 积分图算法介绍 积分图算法是图像处理中的经典算法之一,由Crow在1984年首次提出,它是为了在多尺度透视投影中提高渲染速度。 积分图算法是一种快速计算图像区域和…...
千问3.5-9B参数调优:降低OpenClaw复杂任务token消耗
千问3.5-9B参数调优:降低OpenClaw复杂任务token消耗 1. 为什么需要关注token消耗? 去年冬天第一次用OpenClaw自动整理季度报告时,我被账单吓了一跳——连续运行3天的复杂任务消耗了价值200多美元的token。这让我意识到,在享受自…...
W5500 TCP客户端实战 | 02 - 从寄存器配置到数据收发的完整流程解析
1. W5500网络寄存器配置详解 第一次接触W5500芯片时,我被它密密麻麻的寄存器地址搞得头晕眼花。后来发现只要抓住几个核心寄存器,配置起来就像填快递单一样简单。先说说最关键的四个本地网络寄存器,它们相当于设备的"身份证"&#…...
字节跳动开源Coze后,个人开发者如何快速上手?保姆级教程来了
字节跳动开源Coze实战指南:从零构建AI智能体的完整路径 当字节跳动宣布将Coze平台全面开源时,整个开发者社区为之振奋。这个被称作"AI智能体全栈工厂"的平台,如今终于揭开了神秘面纱,让个人开发者能够深入探索其技术内核…...
用C++和Winsock从零搭建一个局域网聊天室(附完整代码)
用C和Winsock构建高效局域网聊天室的实战指南 在当今数字化协作环境中,即时通讯工具已成为团队沟通的标配。虽然市面上已有成熟的商业解决方案,但理解底层网络通信原理对于开发者而言至关重要。本文将带你从零开始,用C和Winsock API构建一个…...
CSS 语音参考
CSS 语音参考 概述 CSS(层叠样式表)是网页设计中的核心组成部分,它允许开发者控制网页元素的样式,包括颜色、布局、字体等。在网页设计中,有时我们需要为特定的元素添加语音提示,以便于视觉障碍者或需要语音辅助的用户使用。本文将详细探讨CSS中语音参考的实现方法,包…...
akdbdudhdhfvf
一、OpenAI 1.OpenAI是什么简单来说,OpenAI 大模型 是由美国人工智能公司 OpenAI 开发的一系列大型语言模型(LLMs) 。你可以把它们想象成拥有巨大“知识储备”和“学习能力”的超级大脑,它们被训练用来理解和生成人类语言…...
率零测评:AI率83%的文章降完是什么效果
率零(www.0ailv.com)最大的特点是便宜——3.2元/千字,在主流工具里价格最低,还有1000字免费体验。这让很多AI率高的同学把它作为第一选择。 它的实际效果怎么样?这篇文章来说清楚。 测试基本情况 测试论文ÿ…...
4步高效实现OneNote Markdown导出:从迁移到深度应用指南
4步高效实现OneNote Markdown导出:从迁移到深度应用指南 【免费下载链接】onenote-md-exporter ConsoleApp to export OneNote notebooks to Markdown formats 项目地址: https://gitcode.com/gh_mirrors/on/onenote-md-exporter 当你需要将多年积累的OneNot…...
Claude Code 进阶攻略:搞定内置 /loop,用大白话玩转 Cron,一行搞定自动化任务
每天免费领 1亿 Token,白嫖DeepSeek、GLM、MiniMax、Kimi等大模型! 本文写给:天天跟 Claude Code 打交道的程序员们,教你把那些烦人的监控活儿从“肉眼盯着”变成“系统自动报”。 等代码构建的时候,你通常在干嘛&…...
UG NX 在曲面上生成文字
在UG NX中,在曲面上生成文字通常有两种方法:“面上”文本(直接贴合)和“曲线”文本投影。方法一:使用“面上”文本(直接生成,最常用) 这种方法生成的字是直接“长”在曲面上的&#…...
