VUE使用websocket

在之前搭建好的项目的基础上新版security demo(二)前端-CSDN博客

目录

一、代码改造

1、后端改造

2、VUE使用websocket

3、测试

二、按用户推送

1、完整代码如下

1.1、前端

1.2、后端:

2、测试


一、代码改造

1、后端改造

(1)把websocket相关代码复制到web项目:

(2)添加白名单

web-socket端口无需token验证,SecurityWebConfig添加白名单

 @Beanpublic WebSecurityCustomizer webSecurityCustomizer() {return (web) -> web.ignoring().requestMatchers("/param/**", "/user-websocket-endpoint/**","/menu-websocket-endpoint/**");}
2、VUE使用websocket
<template><div>this is user manage</div>
</template>
<script>
export default {data() {return {socket: null,message: '',inputMessage: ''};},mounted() {// Create a new WebSocket connectionthis.socket = new WebSocket("ws://localhost:2222/securityDemo/user-websocket-endpoint");// Set up event listenersthis.socket.onopen = (event) => {console.log('WebSocket connection opened.');this.socket.send("Hello Server! This is menu client");};this.socket.onmessage = (event) => {this.message = event.data;};this.socket.onerror = (error) => {console.error('WebSocket Error:', error);};this.socket.onclose = (event) => {console.log('WebSocket connection closed.');};},methods: {sendMessage() {if (this.socket && this.inputMessage) {this.socket.send(this.inputMessage);this.inputMessage = ''; // Clear the input field after sending}}},// beforeDestroy() {//   // Close the WebSocket connection when the component is destroyed//   if (this.socket) {//     this.socket.close();//   }// }
};
</script>

menumanage.vue代码和这个类似。 

3、测试

分别启动前后端,打开浏览器

(1)查看消息收发

切换到菜单管理:

再次切换到user页面,会断开之前的连接重新建立连接,因为vue每次进入页面都会执行mounted。 

idea控制台打印:

(2)postman调用user发送消息接口

浏览器接收成功:

postman调用menu发送消息接口:

浏览器接收成功:

二、按用户推送

 上面的demo,所有的客户端都会接收到消息,现在希望推送给某个user。则需要建立WebSocketSession和userId的关系,

(1)前端在open建立连接时发送userId;

<!DOCTYPE html>
<html>
<head><title>WebSocket Client</title>
</head>
<body><script>const userId = "user123"; // Replace with dynamic user IDconst socket = new WebSocket(`ws://localhost:8080/websocket-endpoint`);socket.onopen = function(event) {console.log("WebSocket connection opened.");socket.send(JSON.stringify({ type: "REGISTER", userId: userId }));};socket.onmessage = function(event) {const message = event.data;console.log("Message from server: " + message);};socket.onclose = function(event) {console.log("WebSocket connection closed.");};socket.onerror = function(error) {console.error("WebSocket Error: " + error);};</script>
</body>
</html>

(2)后端WebSocketHandler存储userId和WebSocketSession的映射关系

import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;
import org.springframework.web.socket.CloseStatus;
import org.springframework.stereotype.Component;import java.io.IOException;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;@Component
public class UserWebSocketHandler extends TextWebSocketHandler {private final ConcurrentMap<String, WebSocketSession> userSessions = new ConcurrentHashMap<>();@Overridepublic void afterConnectionEstablished(WebSocketSession session) throws Exception {String userId = getUserIdFromSession(session);if (userId != null) {userSessions.put(userId, session);System.out.println("WebSocket connection established for userId: " + userId);}}@Overridepublic void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {String userId = getUserIdFromSession(session);if (userId != null) {userSessions.remove(userId);System.out.println("WebSocket connection closed for userId: " + userId);}}public void sendMessageToUser(String userId, String message) throws IOException {WebSocketSession session = userSessions.get(userId);if (session != null && session.isOpen()) {session.sendMessage(new TextMessage(message));}}private String getUserIdFromSession(WebSocketSession session) {// Assuming userId is stored as a session attributereturn (String) session.getAttributes().get("userId");}
}

(3)发送消息时根据userId检索目标WebSocketSession。

1、完整代码如下
1.1、前端
<template><div>this is user manage:{{this.userAccount}}</div>
</template>
<script>
export default {data() {return {socket: null,message: '',inputMessage: ''};},
computed: {userAccount() {return this.$store.getters.name;}
},mounted() {// Create a new WebSocket connectionthis.socket = new WebSocket("ws://localhost:2222/securityDemo/user-websocket-endpoint");// Set up event listenersthis.socket.onopen = (event) => {console.log('WebSocket connection opened.');let msg = {"userAccount":this.userAccount}this.socket.send(JSON.stringify(msg));};this.socket.onmessage = (event) => {this.message = event.data;};this.socket.onerror = (error) => {console.error('WebSocket Error:', error);};this.socket.onclose = (event) => {console.log('WebSocket connection closed.');};},methods: {sendMessage() {if (this.socket && this.inputMessage) {this.socket.send(this.inputMessage);this.inputMessage = ''; // Clear the input field after sending}}},// beforeDestroy() {//   // Close the WebSocket connection when the component is destroyed//   if (this.socket) {//     this.socket.close();//   }// }
};
</script>
1.2、后端:

 (1)常量

package com.demo.security.ws.constant;import lombok.Getter;
import org.springframework.web.socket.WebSocketSession;import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;public class UserSessionConstant {@Getterprivate static Map<String,WebSocketSession> sessionMap = new HashMap<>();public static void add(String userId,WebSocketSession session) {sessionMap.put(userId,session);}public static void remove(WebSocketSession session) {//从map中找到key,再remove key//sessionMap.remove(userAccount);}
}

(2)ws操作

package com.demo.security.ws;import com.demo.security.dto.MsgDTO;
import com.demo.security.dto.UserDTO;
import com.demo.security.ws.constant.UserSessionConstant;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
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;import java.io.IOException;@Component
@Slf4j
public class UserWebSocketHandler extends TextWebSocketHandler {@Overridepublic void afterConnectionEstablished(WebSocketSession session) throws Exception {//UserSessionConstant.add(session);log.info("user有新的连接,sessionId:{}",session.getId());}@Overridepublic void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {// 处理接收到的消息log.info("user服务端Received message: {}",message.getPayload());String payLoad = message.getPayload();ObjectMapper objectMapper = new ObjectMapper();MsgDTO msgDTO = objectMapper.readValue(payLoad, MsgDTO.class);UserSessionConstant.add(msgDTO.getUserAccount(),session);}@Overridepublic void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {UserSessionConstant.remove(session);log.info("user连接已断开sessionId:{}",session.getId());}public void sendMessageToAll(String message) {for(WebSocketSession session : UserSessionConstant.getSessionMap().values()) {if (session.isOpen()) {try {session.sendMessage(new TextMessage(message));log.info("user发送消息给{}成功",session.getId());} catch (IOException e) {e.printStackTrace();}}}}public void sendMessageToUser(String message,String userAccount) {for(String sessionUserAccount : UserSessionConstant.getSessionMap().keySet()){if(!userAccount.equals(sessionUserAccount)){continue;}WebSocketSession session = UserSessionConstant.getSessionMap().get(userAccount);if (session.isOpen()) {try {session.sendMessage(new TextMessage(message));log.info("user发送消息给用户{}成功",userAccount);} catch (IOException e) {e.printStackTrace();}}}}
}

 (3)controller接口

package com.demo.security.controller;import com.demo.security.dto.UserDTO;
import com.demo.security.ws.UserWebSocketHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
@RequestMapping("/userMsg")
public class UserMsgController {@Autowiredprivate UserWebSocketHandler userWebSocketHandler;@RequestMapping("/send")public void sendMessage(UserDTO messageDTO) {userWebSocketHandler.sendMessageToUser(messageDTO.toString(),messageDTO.getUserAccount());}
}
2、测试

(1)

打开两个浏览器,分别登录zs、admin

后端断点可以看到map存储了两条数据:

(2)调用postman接口给zs发送消息:

查看浏览器,zs的账号接收到了消息,admin的没有接收到:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/411181.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

逆波兰表达式

简介 介绍逆波兰表达式之前&#xff0c;先介绍一下运算种类。 中缀运算与后缀运算 中缀运算是一种常用的算术和逻辑公式表示方法&#xff0c;其中操作符位于两个运算数之间。例如&#xff0c;在表达式 “3 2” 中&#xff0c;加号&#xff08;&#xff09;是操作符&#xf…

算法设计:实验一分治与递归

【实验目的】 深入理解分治法的算法思想&#xff0c;应用分治法解决实际的算法问题。 【实验内容与要求】 设有n2k个运动员要进行网球循环赛。现要设计一个满足以下要求的比赛日程表&#xff1a; 1.每个选手必须与其他n-1个选手各赛一次&#xff1b;2.每个选手一天只能赛一…

Mysql 集群技术

目录 一 Mysql 在服务器中的部署方法 1.1 在Linux下部署mysql 1.1.1 安装依赖性并解压源码包&#xff0c;源码编译安装mysql&#xff1a; 1.1.2 部署mysql 二 mysql的组从复制 2.1 配置mastesr和salve 测试结果 2.2 当有数据时添加slave2 2.3 延迟复制 2.4 慢查询日志…

【C++ | 设计模式】简单工厂模式的详解与实现

1.简单工厂模式概述 简单工厂模式&#xff08;Simple Factory Pattern&#xff09;是一种创建型设计模式&#xff0c;它定义了一个工厂类&#xff0c;由这个类根据提供的参数决定创建哪种具体的产品对象。简单工厂模式将对象的创建逻辑集中到一个工厂类中&#xff0c;从而将对…

Python-进阶-Excel基本操作

文章目录 Excel 基本操作1. 概述2. 写入2.1 使用 xlwt2.2 使用 XlsxWriter 3. 读取4. 修改 Excel 基本操作 1. 概述 在数据处理方面&#xff0c;Python 一直扮演着重要的角色&#xff0c;对于 Excel 操作&#xff0c;它有着完整且成熟的第三方库&#xff0c;使用也较为简单。…

视频结构化从入门到精通——认识视频结构化

认识视频结构化 1. 视频结构化与非结构化 1. 非结构化数据 非结构化数据指的是未经处理、以原始形式存在的数据。这类数据是直接采集、记录的&#xff0c;包含了音频、视频等多维信息&#xff0c;且没有任何标签、注释或分类来表示其中的内容。非结构化数据需要进一步处理和…

AI视频平台精选:国内外对比与推荐

原文&#xff1a;AI视频平台精选&#xff1a;国内外对比与推荐 国内外有多个平台可以生成AI视频&#xff0c;这些平台各有其独特的优点和缺点。以下是对一些主要平台的详细介绍&#xff0c;包括它们的优缺点&#xff0c;以及针对个人和自媒体用户的推荐。 国内平台 1. 快手可…

Android 架构模式之 MVVM

Android 架构 Android 架构模式之 MVCAndroid 架构模式之 MVPAndroid 架构模式之 MVVM 目录 Android 架构架构设计的目的对 MVVM 的理解代码ModelViewViewModel Android 中 MVVM 的问题试吃个小李子BeanModelViewViewModel效果展示 大家好&#xff01; 作为 Android 程序猿&a…

代码随想录算法训练营第13天 |二叉树的学习

目录 二叉树 理论基础 二叉树的分类 1. 满二叉树 (Full Binary Tree) 2. 完全二叉树 (Complete Binary Tree) 3. 平衡二叉树 (Balanced Binary Tree) 5. 二叉搜索树 (Binary Search Tree, BST) 二叉树的存储 1. 链式存储 (Linked Representation) 2. 顺序存储 (Sequent…

Golang | Leetcode Golang题解之第363题矩形区域不超过K的最大数值和

题目&#xff1a; 题解&#xff1a; import "math/rand"type node struct {ch [2]*nodepriority intval int }func (o *node) cmp(b int) int {switch {case b < o.val:return 0case b > o.val:return 1default:return -1} }func (o *node) rotate…

pyro 教程 时间序列 单变量,重尾,python pytorch,教程和实例 Forecasting预测,布朗运动项、偏差项和协变量项

预测I:单变量&#xff0c;重尾 本教程介绍了预测模块&#xff0c;用Pyro模型进行预测的框架。本教程只涵盖单变量模型和简单的可能性。本教程假设读者已经熟悉慢病毒感染和张量形状. 另请参见: 预测II:状态空间模型 预测三:层次模型 摘要 要创建预测模型: 创建预测模型班级…

算法笔试-编程练习-H-02-24

w这套题&#xff0c;侧重模拟和题目理解&#xff0c;只要按照题目描述正常复现整体分数应该不错 一、数据重删 数据重删是一种节约存储空间的技术&#xff0c;通常情况下&#xff0c;在数据存储池内是有很多重复的数据库。重删则是将这些重复的数据块找出并处理的技术。简单地…

Java:jdk8之后新增的时间API

文章目录 为什么要使用新增的API新增了哪些&#xff1f;Local常用方法代码一样的用法 黑马学习笔记 使用新增的 为什么要使用新增的API 新增了哪些&#xff1f; Local 常用方法 代码 package NewTime;import java.time.LocalDate;/*** Author: ggdpzhk* CreateTime: 2024-08-…

竞猜足球核心算法源码

需要实现的功能如下&#xff1a; 仅用于学习 竞猜足球核心算法源码 package com.lotterysource.portsadmin.service; import com.aliyun.oss.common.utils.DateUtil; import com.fasterxml.jackson.core.type.TypeReference; import com.lotterysource.portsadmin.dbprovid…

@ohos.systemParameterEnhance系统参数接口调用:控制设备硬件(执行shell命令方式)

本文介绍如何使用应用ohos.systemParameterEnhance (系统参数)(系统接口)来控制设备硬件&#xff0c;可以通过它在系统中执行一段shell命令&#xff0c;从而实现控制设备的效果。接下来以一个实际的样例来演示如何通过它来控制设备以太网接口 开源地址&#xff1a;https://git…

链表OJ题——环形链表2

文章目录 一、题目链接二、解题思路三、解题代码 一、题目链接 环形链表2 题目描述&#xff1a;在链表有环的基础上&#xff0c;找出环的入口点。 二、解题思路 三、解题代码

超实用的8个无版权、免费、高清图片素材网站整理

不管是设计、文章配图&#xff0c;还是视频制作&#xff0c;图片都至关重要。但是图片版权一直都是困扰很多设计、自媒体以及企业的大问题。现在&#xff0c;因为图片侵权被告的案例已经是司空见惯了&#xff0c;有的公众号甚至因为图片版权问题遭受致命打击。 1. Pexels Pexe…

(经验)SVN降版本,保留版本信息和用户信息。

背景&#xff1a;由于开始公司人数规模小&#xff0c;没有关心SVN最新版本免费对于用户数量限制要求不敏感&#xff0c;随着人数越来越多&#xff0c;公司来了新员工已经添加不了SVN需要注册码了&#xff0c;不利于SVN文件管理的在公司内部的推广。看了好多资料&#xff0c;都没…

信息学奥赛初赛天天练-75-NOIP2016普及组-完善程序-二分答案、二分查找、贪心算法、贪心策略

文章PDF链接: https://pan.baidu.com/s/1SVcGU_rApvoUWrUoviPCiA?pwdht2j 提取码: ht2j 复制这段内容后打开百度网盘手机App&#xff0c;操作更方便哦 1 完善程序 (单选题 &#xff0c;每小题3分&#xff0c;共30分) 郊游活动 有 n名同学参加学校组织的郊游活动&#xff0c…

有没有比较好用的在线翻译工具?实力推荐这4款。

当我们面对外文资料时&#xff0c;可能需要翻阅厚重的词典&#xff0c;耗费大量的时间和精力。在翻译这方面&#xff0c;很多人都十分依赖翻译工具的&#xff0c;因为这些工具只需几秒钟就能给出翻译结果&#xff0c;提高了我们的学习和工作的效率。但是随着翻译工具越来阅读&a…