springBoot与Vue共同搭建webSocket环境
欢迎使用Markdown编辑器
你好! 这片文章将教会你从后端springCloud到前端VueEleementAdmin如何搭建Websocket
前端
1. 创建websocket的配置文件在utils文件夹下websocket.js
// 暴露自定义websocket对象
export const socket = {// 后台请求路径url: '',websocketCount: -1,// websocket对象websocket: null,// websocket状态websocketState: false,// 重新连接次数reconnectNum: 0,// 重连锁状态,保证重连按顺序执行lockReconnect: false,// 定时器信息timeout: null,clientTimeout: null,serverTimeout: null,// 初始化方法,根据url创建websocket对象封装基本连接方法,并重置心跳检测initWebSocket(newUrl) {socket.url = newUrlsocket.websocket = new WebSocket(socket.url)socket.websocket.onopen = socket.websocketOnOpensocket.websocket.onerror = socket.websocketOnErrorsocket.websocket.onmessage = socket.webonmessagesocket.websocket.onclose = socket.websocketOnClosethis.resetHeartbeat()},reconnect() {// 判断连接状态console.log('判断连接状态')if (socket.lockReconnect) returnsocket.reconnectNum += 1// 重新连接三次还未成功调用连接关闭方法if (socket.reconnectNum === 3) {socket.reconnectNum = 0socket.websocket.onclose()return}// 等待本次重连完成后再进行下一次socket.lockReconnect = true// 5s后进行重新连接socket.timeout = setTimeout(() => {socket.initWebSocket(socket.url)socket.lockReconnect = false}, 5000)},// 重置心跳检测resetHeartbeat() {socket.heartbeat()},// 心跳检测heartbeat() {socket.clientTimeout = setTimeout(() => {if (socket.websocket) {// 向后台发送消息进行心跳检测socket.websocket.send(JSON.stringify({ type: 'heartbeat' }))socket.websocketState = false// 一分钟内服务器不响应则关闭连接socket.serverTimeout = setTimeout(() => {if (!socket.websocketState) {socket.websocket.onclose()console.log('一分钟内服务器不响应则关闭连接')} else {this.resetHeartbeat()}}, 60 * 1000)}}, 3 * 1000)},// 发送消息sendMsg(message) {socket.websocket.send(message)},websocketOnOpen(event) {// 连接开启后向后台发送消息进行一次心跳检测socket.sendMsg(JSON.stringify({ type: 'heartbeat' }))},// 初始化websocket对象// window.location.host获取ip和端口,// process.env.VUE_APP_WEBSOCKET_BASE_API获取请求前缀// 绑定接收消息方法webonmessage(event) {// 初始化界面时,主动向后台发送一次消息,获取数据this.websocketCount += 1if (this.websocketCount === 0) {const queryCondition = {type: 'message'}socket.sendMsg(JSON.stringify(queryCondition))console.log('初始化界面时,主动向后台发送一次消息,获取数据')}const info = JSON.parse(event.data)switch (info.type) {case 'heartbeat':socket.websocketState = trueconsole.log(JSON.stringify(info))breakcase 'message':if (info.message === '成功') {this.$notify({title: '提示',message: '成功',type: 'success',duration: 0})} else {this.$notify({title: '提示',message: '上传失败:' + info.message,type: 'warning',duration: 0})}breakcase 'error':console.log('websocket:error')break}},websocketOnError(error) {console.log(error)console.log('websocket报错了' + error)socket.reconnect()},websocketOnClose() {console.log('websocke他关闭了')socket.websocket.close()}
}
2. 在main.js中引入配置文件,使websocket全局都能使用
3. 设置登陆时开启websocket连接,
this. s o c k e t . i n i t W e b S o c k e t ( ‘ w s : socket.initWebSocket( `ws: socket.initWebSocket(‘ws:{process.env.VUE_APP_WEBSOCKET_BASE_API}/websocket/` + this.loginForm.username
) 这句是开启websocket连接的。
// 登录方法
handleLogin() {this.$refs.loginForm.validate(valid => {if (valid) {this.loading = truethis.$store.dispatch('user/login', this.loginForm).then(() => {this.$router.push({ path: this.redirect || '/', query: this.otherQuery })this.$store.dispatch('user/addInfomation', this.infoMation)this.$socket.initWebSocket(`ws:${process.env.VUE_APP_WEBSOCKET_BASE_API}/websocket/` + this.loginForm.username)this.loading = false}).catch(() => {this.loading = false})} else {console.log('error submit!!')return false}})
},
4. 设置退出时关闭websocket连接
this.$socket.websocketOnClose()这句是关闭websocket连接的
logout() {await this.$store.dispatch('user/logout')this.$socket.websocketOnClose()this.$router.push(`/login?redirect=${this.$route.fullPath}`)}
重点和需要配置的地方都在websocket.js里比如接收消息方法webonmessage
后端
1.引依赖
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId></dependency>
2.写配置
package com.szc.material.analysisService.confg.WebSocket;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;@Configuration
public class WebSocketConfig {/*** 注入ServerEndpointExporter,* 这个bean会自动注册使用了@ServerEndpoint注解声明的Websocket endpoint*/@Beanpublic ServerEndpointExporter serverEndpointExporter() {return new ServerEndpointExporter();}}
3.创建Websocket服务类(依据自己的业务去改@OnMessage方法)
package com.szc.material.analysisService.confg.WebSocket;import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;import javax.security.auth.message.MessageInfo;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;/*** @author zhj* @ServerEndpoint:将目前的类定义成一个websocket服务器端,注解的值将被用于监听用户连接的终端访问URL地址,客户端可以通过这个URL来连接到WebSocket服务器端* @OnOpen:当WebSocket建立连接成功后会触发这个注解修饰的方法。* @OnClose:当WebSocket建立的连接断开后会触发这个注解修饰的方法。* @OnMessage:当客户端发送消息到服务端时,会触发这个注解修改的方法。* @OnError:当WebSocket建立连接时出现异常会触发这个注解修饰的方法。* ————————————————* 版权声明:本文为CSDN博主「人人都在发奋」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。* 原文链接:https://blog.csdn.net/qq991658923/article/details/127022522*/
@Component
@Slf4j
@ServerEndpoint("/websocket/{userId}")
public class MyWebSocketHandler extends TextWebSocketHandler {/*** 线程安全的无序的集合*/private static final CopyOnWriteArraySet<Session> SESSIONS = new CopyOnWriteArraySet<>();/*** 存储在线连接数*/private static final Map<String, Session> SESSION_POOL = new HashMap<>();@OnOpenpublic void onOpen(Session session, @PathParam(value = "userId") String userId) {try {SESSIONS.add(session);SESSION_POOL.put(userId, session);log.info("【WebSocket消息】有新的连接,总数为:" + SESSIONS.size());} catch (Exception e) {e.printStackTrace();}}@OnClosepublic void onClose(Session session,@PathParam(value = "userId") String userId) {try {SESSIONS.remove(session);SESSION_POOL.remove(userId);log.info("【WebSocket消息】连接断开,总数为:" + SESSION_POOL.size());} catch (Exception e) {e.printStackTrace();}}@OnMessagepublic void onMessage(String message, @PathParam(value = "userId") String userId) {JSONObject jsonObject = JSON.parseObject(message);if("heartbeat".equals(jsonObject.get("type").toString())){Map<String,String> messageInfor=new HashMap<>();messageInfor.put("type","heartbeat");messageInfor.put("message","我收到了你的心跳");sendOneMessage( userId,messageInfor);log.info("【WebSocket消息】收到客户端消息:" + message);}}/*** 此为广播消息** @param message 消息*/public void sendAllMessage(String message) {log.info("【WebSocket消息】广播消息:" + message);for (Session session : SESSIONS) {try {if (session.isOpen()) {session.getAsyncRemote().sendText(message);}} catch (Exception e) {e.printStackTrace();}}}/*** 此为单点消息** @param userId 用户编号* @param message 消息*/public void sendOneMessage(String userId, Map<String,String> message) {Session session = SESSION_POOL.get(userId);if (session != null && session.isOpen()) {try {synchronized (session) {log.info("【WebSocket消息】单点消息:" + message.get("message"));session.getAsyncRemote().sendText(JSON.toJSONString(message));}} catch (Exception e) {e.printStackTrace();}}}/*** 此为单点消息(多人)** @param userIds 用户编号列表* @param message 消息*/public void sendMoreMessage(String[] userIds, String message) {for (String userId : userIds) {Session session = SESSION_POOL.get(userId);if (session != null && session.isOpen()) {try {log.info("【WebSocket消息】单点消息:" + message);session.getAsyncRemote().sendText(message);} catch (Exception e) {e.printStackTrace();}}}}}
4.在需要的地方进行调用
(1)先注入websocket服务类
@AutowiredMyWebSocketHandler myWebSocketHandler;
(2)在方法中调用给前端发消息的方法
myWebSocketHandler.sendOneMessage(userId,messageInfor);
问题:
1.如果你在controller层调用了service层中身为异步的方法出现了HttpServeletrequst空指针你需要在controller层调用异步方法前加入下面的代码。
ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();RequestContextHolder.getRequestAttributes().setAttribute("request", request, RequestAttributes.SCOPE_REQUEST);RequestContextHolder.setRequestAttributes(servletRequestAttributes,true);//设置子线程共享
调用requst中的参数时必须使用下面的方法
HttpServletRequest request2 = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();if( request2.getHeader(UserContext.USER_NAME)!=null){return Optional.of(request2.getHeader(UserContext.USER_NAME));}
相关文章:

springBoot与Vue共同搭建webSocket环境
欢迎使用Markdown编辑器 你好! 这片文章将教会你从后端springCloud到前端VueEleementAdmin如何搭建Websocket 前端 1. 创建websocket的配置文件在utils文件夹下websocket.js // 暴露自定义websocket对象 export const socket {// 后台请求路径url: ,websocketCo…...

【Python】collections.Counter
Python内置模块collections中的Counter是字典子类。Counter不是字典,但很像字典。 Counter具有字典的键和值,键是各个元素,值为该元素出现的次数。 Counter相当于计数器。常用于哈希映射(哈希表)。 from collection…...

【Elasticsearch】es脚本编程使用详解
目录 一、es脚本语言介绍 1.1 什么是es脚本 1.2 es脚本支持的语言 1.3 es脚本语言特点 1.4 es脚本使用场景 二、环境准备 2.1 docker搭建es过程 2.1.1 拉取es镜像 2.1.2 启动容器 2.1.3 配置es参数 2.1.4 重启es容器并访问 2.2 docker搭建kibana过程 2.2.1 拉取ki…...
Synchronized 关键字
在Java中,线程同步使用最多的方法是使用synchronized关键字。每个Java对象都隐含有一把锁,这里称为Java内置锁(或者对象锁、隐式锁)。使用synchronized(syncObject)调用相当于获取 syncObject 的内置锁,所以可以使用内置锁对临界区代码段进行…...

Maven系列第8篇:大型Maven项目,快速按需任意构建
本篇涉及到的内容属于神技能,多数使用maven的人都经常想要的一种功能,但是大多数人都不知道如何使用,废话不多说,上干货。 需求背景 我们需要做一个电商项目,一般都会做成微服务的形式,按业务进行划分&am…...
卷积神经网络(CNN)的组成结构以及其优点
卷积神经网络(Convolutional Neural Network,简称CNN)是一种深度学习模型,主要用于处理具有网格结构的数据,如图像和视频。它的结构包含以下几个关键组件: 卷积层(Convolutional Layerÿ…...

[③ADRV902x]: Digital Filter Configuration(接收端)
前言 本篇博客主要总结了ADRV9029 Rx接收端链路中各个滤波器的配置。配置不同的滤波器系数以及不同的参数,可以对输入的数字信号灵活得做decimation处理,decimation信号抽取,就是降低信号采样率的过程。 Receiver Signal Path 下图为接收端…...

企业安全—DevSecOps概述详情
0x00 前言 SDL存在的问题在于体量过于庞大,不利于快速进行适配和进行,所以就有了DevSecOps,实际上是因为敏捷开发也就是DevOps的推进,并且坐上了云服务模式的火车,所以这一系列的东西都开始普及。DevSecOps作为DevOps…...

数据结构与算法(十):动态规划与贪心算法
参考引用 Hello 算法 Github:hello-algo 1. 动态规划算法 动态规划将一个问题分解为一系列更小的子问题,并通过存储子问题的解来避免重复计算,从而大幅提升时间效率 问题:给定一个共有 n 阶的楼梯,你每步可以上 1 阶或…...

【C++代码】安排行程,N皇后,解数独--代码随想录
题目:重新安排行程 给你一份航线列表 tickets ,其中 tickets[i] [fromi, toi] 表示飞机出发和降落的机场地点。请你对该行程进行重新规划排序。所有这些机票都属于一个从 JFK(肯尼迪国际机场)出发的先生,所以该行程必…...

SpringCloud Alibaba【二】nacos
nacos配置与使用 nacos初步使用nacos安装与配置创建命名空间 nacos使用与配置创建新项目作为父项目 创建nacos服务端项目pom.xmlapplication.yml启动类 创建nacos客户端项目pom.xml application.yml启动类 启动测试 nacos配置负载均衡改造生产者nacos-provider-projectcontroll…...
C++中的fsanitize指令
一个集成在 gcc、clang 编译器中的编译指令,可以有效测试程序中的一些诸如数组越界、未定义行为等情况。 举个例子: #include <bits/stdc.h> using namespace std;const int maxn2e55,mxr1e5,maxm1e75; int head[maxn],nxt[maxn],to[maxn],f[max…...

【AI视野·今日Robot 机器人论文速览 第五十八期】Thu, 19 Oct 2023
AI视野今日CS.Robotics 机器人学论文速览 Thu, 19 Oct 2023 Totally 25 papers 👉上期速览✈更多精彩请移步主页 Daily Robotics Papers InViG: Benchmarking Interactive Visual Grounding with 500K Human-Robot Interactions Authors Hanbo Zhang, Jie Xu, Yuch…...

Java截取(提取)子字符串(substring()),Java分割字符串(split())
在 String 中提供了两个截取字符串的方法,一个是从指定位置截取到字符串结尾,另一个是截取指定范围的内容。下面对这两种方法分别进行介绍。 1. substring(int beginIndex) 形式 此方式用于提取从索引位置开始至结尾处的字符串部分。调用时,…...

从厨房间到股市:家庭主妇的华美转身
我一直是一个安于现状的家庭主妇。生活中,我热爱烹饪、园艺和照顾家人,但我也渴望能有更多的自我实现和价值感。在机缘巧合下,我接触到了卓扬网,一个专业的股票投资平台。从那刻起,我的人生发生了翻天覆地的变化。 初…...
Oracle 数据库的锁排查方法
关键字 oracle lock 问题描述 Oracle 数据库上锁问题如何排查 解决问题思路 准备数据 create table lock_test(name varchar(10),age varchar(10));insert into lock_test values(ff,10); insert into lock_test values(yy,20); insert into lock_test values(ll,30);Orac…...

混合精度训练原理之float16和float32数据之间的互相转换
混合精度训练原理之float16和float32数据之间的互相转换 本篇文章参考:全网最全-混合精度训练原理 上述文章已经讲解的比较详细,本文只是从数值角度分析: 1. float32转入float16的精度误差 2. 在深度学习的混精度训练当中,当参数…...

网络协议--ICMP:Internet控制报文协议
6.1 引言 ICMP经常被认为是IP层的一个组成部分。它传递差错报文以及其他需要注意的信息。ICMP报文通常被IP层或更高层协议(TCP或UDP)使用。一些ICMP报文把差错报文返回给用户进程。 ICMP报文是在IP数据报内部被传输的,如图6-1所示。 ICMP…...

《红蓝攻防对抗实战》三.内网探测协议出网之HTTP/HTTPS协议探测出网
目录 一. 在 Windows 操作系统中探测 HTTP/HTTPS 出网 1. Bitsadmin 命令 2.Certuil 命令 2.Linux系统探测HTTP/HTTPS出网 1.Curl命令 2.Wget命令 对目标服务器探测 HTTP/HTTPS 是否出网时,要根据目标系统类型执行命令,不同类型的操作系统使用的探…...

【Win11】系统重装教程(最新最详细)
目录 一.简介 二.用U盘制作PE系统 三、安装系统 软件:Windows 11版本:21H2语言:简体中文大小:5.14G安装环境:PE系统,至少7代处理器硬件要求:CPU2.0GHz 内存4G(或更高)下载通道①丨…...

基于PSO粒子群优化的VMD-GRU时间序列预测算法matlab仿真
目录 1.前言 2.算法运行效果图预览 3.算法运行软件版本 4.部分核心程序 5.算法仿真参数 6.算法理论概述 6.1变分模态分解(VMD) 6.2 门控循环单元(GRU) 6.3 粒子群优化(PSO) 7.参考文献 8.算法完…...
jenkins结合gitlab实现CI
Jenkins结合GitLab实现CI(持续集成) 持续集成(Continuous Integration, CI)是一种软件开发实践,开发者在代码提交后,系统会自动进行构建、测试,从而尽早发现问题。Jenkins和GitLab的结合可以高效…...
高效图像处理:使用 Pillow 进行格式转换与优化
高效图像处理:使用 Pillow 进行格式转换与优化 1. 背景引入 在图像处理应用中,格式转换、裁剪、压缩等操作是常见需求。Python 的 Pillow 库基于 PIL(Python Imaging Library),提供 轻量、强大 的图像处理能力,广泛用于 Web 开发、数据分析、机器学习 等领域。 本文将…...
web前端开发如何适配各分辨率
在开发Web应用时,适配不同的显示器分辨率是确保用户体验一致性的关键。以下是一些常见的显示器分辨率。 常见的显示器分辨率 PC屏幕分辨率 1366 x 768:普通液晶显示器 1920 x 1080:高清液晶显示器 2560 x 1440:2K高清显示器 4096…...

GIC v3 v4 虚拟化架构
ARMV8-A架构中包含了对虚拟化的支持。为了与架构保持匹配,GICV3也对虚拟化做了支持。新增了以下特性: 对CPU interface的硬件虚拟化虚拟中断maintenance 中断:用于通知监管程序(例如hypervisor)一些特定的虚拟机事件 …...

创客匠人:以 AI 利器赋能创始人 IP 打造,加速知识变现新路径
在知识付费与个人 IP 崛起的时代,创客匠人作为行业领先的技术服务商,正通过 AI 工具重构创始人 IP 打造与知识变现的生态。其推出的三大 AI 利器 ——AI 销售信、免训数字人、AI 智能客服,精准解决 IP 运营中的核心痛点。 以 AI 销售信为例&…...

Kyosan K5BMC ELECTRONIC INTERLOCKING MANUAL 电子联锁
Kyosan K5BMC ELECTRONIC INTERLOCKING MANUAL 电子联锁...

html文字红色粗体,闪烁渐变动画效果
1. 代码 <!DOCTYPE html> <html lang"zh"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>红色粗体闪烁文字表格</title><s…...

如何让AI自己检查全文?使用OCR和LLM实现自动“全文校订”(可DIY校订规则)
详细流程及描述参见仓库(如果有用的话,请给个收藏): GitHub - xurongtang/DocRevision_Proj: A simple project about how to revist docment (such as your academic paper) in a automatic way with the help of OCR and LLM.A…...

Visual Studio问题记录
程序"xxx dotnet.exe"已退出,返回值为-2147450730 问deepseek:visual studio输出程序dotnet.exe已退出,返回值为-2147450730 dotnet.exe 编译时退出并返回错误代码 **-2147450730**(十六进制 0x80008076)&…...