当前位置: 首页 > news >正文

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全局都能使用

import { socket } from './utils/websocket'
Vue.prototype.$socket = socket

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编辑器 你好&#xff01; 这片文章将教会你从后端springCloud到前端VueEleementAdmin如何搭建Websocket 前端 1. 创建websocket的配置文件在utils文件夹下websocket.js // 暴露自定义websocket对象 export const socket {// 后台请求路径url: ,websocketCo…...

【Python】collections.Counter

Python内置模块collections中的Counter是字典子类。Counter不是字典&#xff0c;但很像字典。 Counter具有字典的键和值&#xff0c;键是各个元素&#xff0c;值为该元素出现的次数。 Counter相当于计数器。常用于哈希映射&#xff08;哈希表&#xff09;。 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中&#xff0c;线程同步使用最多的方法是使用synchronized关键字。每个Java对象都隐含有一把锁&#xff0c;这里称为Java内置锁(或者对象锁、隐式锁)。使用synchronized(syncObject)调用相当于获取 syncObject 的内置锁&#xff0c;所以可以使用内置锁对临界区代码段进行…...

Maven系列第8篇:大型Maven项目,快速按需任意构建

本篇涉及到的内容属于神技能&#xff0c;多数使用maven的人都经常想要的一种功能&#xff0c;但是大多数人都不知道如何使用&#xff0c;废话不多说&#xff0c;上干货。 需求背景 我们需要做一个电商项目&#xff0c;一般都会做成微服务的形式&#xff0c;按业务进行划分&am…...

卷积神经网络(CNN)的组成结构以及其优点

卷积神经网络&#xff08;Convolutional Neural Network&#xff0c;简称CNN&#xff09;是一种深度学习模型&#xff0c;主要用于处理具有网格结构的数据&#xff0c;如图像和视频。它的结构包含以下几个关键组件&#xff1a; 卷积层&#xff08;Convolutional Layer&#xff…...

[③ADRV902x]: Digital Filter Configuration(接收端)

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

企业安全—DevSecOps概述详情

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

数据结构与算法(十):动态规划与贪心算法

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

【C++代码】安排行程,N皇后,解数独--代码随想录

题目&#xff1a;重新安排行程 给你一份航线列表 tickets &#xff0c;其中 tickets[i] [fromi, toi] 表示飞机出发和降落的机场地点。请你对该行程进行重新规划排序。所有这些机票都属于一个从 JFK&#xff08;肯尼迪国际机场&#xff09;出发的先生&#xff0c;所以该行程必…...

SpringCloud Alibaba【二】nacos

nacos配置与使用 nacos初步使用nacos安装与配置创建命名空间 nacos使用与配置创建新项目作为父项目 创建nacos服务端项目pom.xmlapplication.yml启动类 创建nacos客户端项目pom.xml application.yml启动类 启动测试 nacos配置负载均衡改造生产者nacos-provider-projectcontroll…...

C++中的fsanitize指令

一个集成在 gcc、clang 编译器中的编译指令&#xff0c;可以有效测试程序中的一些诸如数组越界、未定义行为等情况。 举个例子&#xff1a; #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 &#x1f449;上期速览✈更多精彩请移步主页 Daily Robotics Papers InViG: Benchmarking Interactive Visual Grounding with 500K Human-Robot Interactions Authors Hanbo Zhang, Jie Xu, Yuch…...

Java截取(提取)子字符串(substring()),Java分割字符串(split())

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

从厨房间到股市:家庭主妇的华美转身

我一直是一个安于现状的家庭主妇。生活中&#xff0c;我热爱烹饪、园艺和照顾家人&#xff0c;但我也渴望能有更多的自我实现和价值感。在机缘巧合下&#xff0c;我接触到了卓扬网&#xff0c;一个专业的股票投资平台。从那刻起&#xff0c;我的人生发生了翻天覆地的变化。 初…...

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数据之间的互相转换 本篇文章参考&#xff1a;全网最全-混合精度训练原理 上述文章已经讲解的比较详细&#xff0c;本文只是从数值角度分析&#xff1a; 1. float32转入float16的精度误差 2. 在深度学习的混精度训练当中&#xff0c;当参数…...

网络协议--ICMP:Internet控制报文协议

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

《红蓝攻防对抗实战》三.内网探测协议出网之HTTP/HTTPS协议探测出网

目录 一. 在 Windows 操作系统中探测 HTTP/HTTPS 出网 1. Bitsadmin 命令 2.Certuil 命令 2.Linux系统探测HTTP/HTTPS出网 1.Curl命令 2.Wget命令 对目标服务器探测 HTTP/HTTPS 是否出网时&#xff0c;要根据目标系统类型执行命令&#xff0c;不同类型的操作系统使用的探…...

【Win11】系统重装教程(最新最详细)

目录 一.简介 二.用U盘制作PE系统 三、安装系统 软件&#xff1a;Windows 11版本&#xff1a;21H2语言&#xff1a;简体中文大小&#xff1a;5.14G安装环境&#xff1a;PE系统&#xff0c;至少7代处理器硬件要求&#xff1a;CPU2.0GHz 内存4G(或更高&#xff09;下载通道①丨…...

AI-调查研究-01-正念冥想有用吗?对健康的影响及科学指南

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; &#x1f680; AI篇持续更新中&#xff01;&#xff08;长期更新&#xff09; 目前2025年06月05日更新到&#xff1a; AI炼丹日志-28 - Aud…...

DockerHub与私有镜像仓库在容器化中的应用与管理

哈喽&#xff0c;大家好&#xff0c;我是左手python&#xff01; Docker Hub的应用与管理 Docker Hub的基本概念与使用方法 Docker Hub是Docker官方提供的一个公共镜像仓库&#xff0c;用户可以在其中找到各种操作系统、软件和应用的镜像。开发者可以通过Docker Hub轻松获取所…...

在HarmonyOS ArkTS ArkUI-X 5.0及以上版本中,手势开发全攻略:

在 HarmonyOS 应用开发中&#xff0c;手势交互是连接用户与设备的核心纽带。ArkTS 框架提供了丰富的手势处理能力&#xff0c;既支持点击、长按、拖拽等基础单一手势的精细控制&#xff0c;也能通过多种绑定策略解决父子组件的手势竞争问题。本文将结合官方开发文档&#xff0c…...

连锁超市冷库节能解决方案:如何实现超市降本增效

在连锁超市冷库运营中&#xff0c;高能耗、设备损耗快、人工管理低效等问题长期困扰企业。御控冷库节能解决方案通过智能控制化霜、按需化霜、实时监控、故障诊断、自动预警、远程控制开关六大核心技术&#xff0c;实现年省电费15%-60%&#xff0c;且不改动原有装备、安装快捷、…...

抖音增长新引擎:品融电商,一站式全案代运营领跑者

抖音增长新引擎&#xff1a;品融电商&#xff0c;一站式全案代运营领跑者 在抖音这个日活超7亿的流量汪洋中&#xff0c;品牌如何破浪前行&#xff1f;自建团队成本高、效果难控&#xff1b;碎片化运营又难成合力——这正是许多企业面临的增长困局。品融电商以「抖音全案代运营…...

linux 错误码总结

1,错误码的概念与作用 在Linux系统中,错误码是系统调用或库函数在执行失败时返回的特定数值,用于指示具体的错误类型。这些错误码通过全局变量errno来存储和传递,errno由操作系统维护,保存最近一次发生的错误信息。值得注意的是,errno的值在每次系统调用或函数调用失败时…...

【Go】3、Go语言进阶与依赖管理

前言 本系列文章参考自稀土掘金上的 【字节内部课】公开课&#xff0c;做自我学习总结整理。 Go语言并发编程 Go语言原生支持并发编程&#xff0c;它的核心机制是 Goroutine 协程、Channel 通道&#xff0c;并基于CSP&#xff08;Communicating Sequential Processes&#xff0…...

什么?连接服务器也能可视化显示界面?:基于X11 Forwarding + CentOS + MobaXterm实战指南

文章目录 什么是X11?环境准备实战步骤1️⃣ 服务器端配置(CentOS)2️⃣ 客户端配置(MobaXterm)3️⃣ 验证X11 Forwarding4️⃣ 运行自定义GUI程序(Python示例)5️⃣ 成功效果![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/55aefaea8a9f477e86d065227851fe3d.pn…...

听写流程自动化实践,轻量级教育辅助

随着智能教育工具的发展&#xff0c;越来越多的传统学习方式正在被数字化、自动化所优化。听写作为语文、英语等学科中重要的基础训练形式&#xff0c;也迎来了更高效的解决方案。 这是一款轻量但功能强大的听写辅助工具。它是基于本地词库与可选在线语音引擎构建&#xff0c;…...

短视频矩阵系统文案创作功能开发实践,定制化开发

在短视频行业迅猛发展的当下&#xff0c;企业和个人创作者为了扩大影响力、提升传播效果&#xff0c;纷纷采用短视频矩阵运营策略&#xff0c;同时管理多个平台、多个账号的内容发布。然而&#xff0c;频繁的文案创作需求让运营者疲于应对&#xff0c;如何高效产出高质量文案成…...