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

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的没有接收到:

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 跑Boundary-Aware Feature Propagation遇到的问题
  • 【法如faro】三维激光软件Scene2023数据处理(自动配准并转换坐标)流程
  • 【kafa系列】kafka如何保证消息不丢失
  • 常用git命令
  • 提高工作效益方法(一)
  • 循环流网络的费用问题
  • JavaScript 练习题是提升编程技能的好方法
  • 华为云征文|基于Flexus云服务器X实例的应用场景-部署脚手架开源项目若依
  • ECMAScript和JavaScript区别
  • Spring 源码解读:JavaConfig与XML配置的对比实现
  • 汉诺塔递归解决思路图解分析,python代码实现
  • OceanbaseV4模拟题解析
  • Spring Bean 作用域
  • Graylog配置用户权限以及常用搜索语法
  • HTML5 为什么只需要写 <!DOCTYPE HTML>
  • .pyc 想到的一些问题
  • [译]CSS 居中(Center)方法大合集
  • 《微软的软件测试之道》成书始末、出版宣告、补充致谢名单及相关信息
  • 【MySQL经典案例分析】 Waiting for table metadata lock
  • 【React系列】如何构建React应用程序
  • 2017-08-04 前端日报
  • 2018天猫双11|这就是阿里云!不止有新技术,更有温暖的社会力量
  • HTML中设置input等文本框为不可操作
  • Java比较器对数组,集合排序
  • laravel 用artisan创建自己的模板
  • MaxCompute访问TableStore(OTS) 数据
  • PV统计优化设计
  • Spring思维导图,让Spring不再难懂(mvc篇)
  • Work@Alibaba 阿里巴巴的企业应用构建之路
  • 不上全站https的网站你们就等着被恶心死吧
  • 从@property说起(二)当我们写下@property (nonatomic, weak) id obj时,我们究竟写了什么...
  • 对话 CTO〡听神策数据 CTO 曹犟描绘数据分析行业的无限可能
  • 解析带emoji和链接的聊天系统消息
  • [Shell 脚本] 备份网站文件至OSS服务(纯shell脚本无sdk) ...
  • 【云吞铺子】性能抖动剖析(二)
  • linux 淘宝开源监控工具tsar
  • ​探讨元宇宙和VR虚拟现实之间的区别​
  • # 20155222 2016-2017-2 《Java程序设计》第5周学习总结
  • ### RabbitMQ五种工作模式:
  • #Js篇:单线程模式同步任务异步任务任务队列事件循环setTimeout() setInterval()
  • #NOIP 2014# day.1 T3 飞扬的小鸟 bird
  • (C#)获取字符编码的类
  • (zhuan) 一些RL的文献(及笔记)
  • (草履虫都可以看懂的)PyQt子窗口向主窗口传递参数,主窗口接收子窗口信号、参数。
  • (附源码)计算机毕业设计ssm高校《大学语文》课程作业在线管理系统
  • (每日一问)基础知识:堆与栈的区别
  • (七)MySQL是如何将LRU链表的使用性能优化到极致的?
  • (三分钟)速览传统边缘检测算子
  • (转)Android中使用ormlite实现持久化(一)--HelloOrmLite
  • (转载)(官方)UE4--图像编程----着色器开发
  • .apk 成为历史!
  • .Net Redis的秒杀Dome和异步执行
  • .net 怎么循环得到数组里的值_关于js数组
  • .NET/C# 使用 SpanT 为字符串处理提升性能
  • .Net的DataSet直接与SQL2005交互