Vue3(pinia) 整合 SpringWebsocket链接url动态传参

news2025/3/10 5:24:43

前言
👏作者简介:我是笑霸final,一名热爱技术的在校学生。
📝个人主页:个人主页1 || 笑霸final的主页2
📕系列专栏:java专栏
📧如果文章知识点有错误的地方,请指正!和大家一起学习,一起进步👀
🔥如果感觉博主的文章还不错的话,👍点赞👍 + 👀关注👀 + 🤏收藏🤏

目录

  • 一.环境准备
  • 二.vue代码
  • 三.SpringWebsocket相关理论
    • 3.1 AbstractWebSocketHandler
    • 3.2 HttpSessionHandshakeInterceptor
    • 3.3 WebSocketConfigurer
  • 四.spring boot代码
    • 4.1继承AbstractWebSocketHandler
    • 4.2 实现WebSocketConfigurer

一.环境准备

vue3 :官方文档 https://cn.vuejs.org/
pinia:官方文档 https://pinia.vuejs.org/zh/
springWebSocket的maven坐标

 	<dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-websocket</artifactId>
    </dependency>

二.vue代码

pinia的安装和使用就不说了直接看官方文档就行。

1、创建stores/demo.ts

import { defineStore } from 'pinia'
import { ref } from 'vue'

export const useChantStore = defineStore('chant', () => {
  //state
  const msg = ref("")//发送的消息
  var socket= ref() ;
  const userId = ref("")  //传递的参数
  const count = ref(0)  	//链接标志

  //action
  // Websoket连接成功事件
  const websocketonopen = (res: any) => {
    console.log("WebSocket连接成功", res);
  };
  // Websoket接收消息事件
  const websocketonmessage = (res: any) => {
    console.log("数据", res);
    msg.value = res.data

  };
  // Websoket连接错误事件
  const websocketonerror = (res: any) => {
    console.log("连接错误", res);
  };
  // Websoket断开事件
  const websocketclose = (res: any) => {
    console.log("断开连接", res);
    websocketclose;
    // 销毁 websocket 实例对象
    socket.value = null;
    count.value = 0;
    userId.value = '';
  };

  //创建链接
  const connectWebSocket = () =>{
    console.log("websocket创建链接 usrid= ",userId.value);
    const wsurl = `ws://127.0.0.1:8888/api/myWs1?userId=${userId.value}`;
    socket.value = new WebSocket(wsurl);
    socket.value.onopen = websocketonopen;
    socket.value.onmessage = websocketonmessage;
    socket.value.onerror = websocketonerror;
    socket.value.onclose = websocketclose;
    count.value = 1;
  }
  //关闭链接
  const closetWebSocket = () =>{
    websocketclose;
    // 销毁 websocket 实例对象
    socket.value = null;
    count.value = 0;
    userId.value = '';

  }
  

  return { msg, socket,userId,count,connectWebSocket,closetWebSocket }
})

二、在使用的组件中使用

import { useChantStore } from '../stores/chant'
//websocket
const chantWebSocket = useChantStore()
//你自己的代码

三.SpringWebsocket相关理论

主要的接口

在这里插入图片描述

3.1 AbstractWebSocketHandler

AbstractWebSocketHandler:是 Spring Framework 中用于处理 WebSocket 通信的一个基础抽象类,它位于 org.springframework.web.socket.handler 包下。在构建基于Spring的WebSocket应用时,开发者可以扩展这个类来创建自定义的消息处理器。

  • 连接建立与关闭处理

    • void afterConnectionEstablished(WebSocketSession session):当一个新的WebSocket连接建立后,此方法会被调用,开发者可以在其中进行初始化操作或者订阅事件。
    • void handleTransportError(WebSocketSession session, Throwable exception):当在传输层发生错误时调用,可用于处理异常情况和清理资源。
    • void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus):在WebSocket连接关闭后执行,通常用来清理资源或记录日志。
  • 消息处理

    void handleMessage(WebSocketSession session, WebSocketMessage<?> message):这是一个抽象方法,子类需要实现它来处理从客户端接收到的各种类型的消息。

  • 握手协商:

    可以通过重写 boolean supportsPartialMessages() 来表明是否支持分片消息。

  • 其他功能:

    它还可能提供一些便利的方法用于发送消息给客户端、设置会话属性等。

3.2 HttpSessionHandshakeInterceptor

HttpSessionHandshakeInterceptor 是 Spring Framework 中用于 WebSocket 扩展的一个类,它继承自 HandshakeInterceptor 接口,并特别关注于在 WebSocket 握手阶段与 HTTP HttpSession 的交互。

当客户端尝试建立 WebSocket 连接时,会触发一个握手过程,在这个过程中,服务器可以使用 HttpSessionHandshakeInterceptor 来拦截握手请求和响应,以便进行额外的检查、修改握手参数或执行特定的业务逻辑。
通过实现或扩展 HttpSessionHandshakeInterceptor 类,开发人员能够定制WebSocket连接初始化的过程,比如进行权限验证、会话同步以及对跨域支持等需求的处理。

HttpSessionHandshakeInterceptor 提供了两个核心方法

  • beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> attributes):

    • 在握手开始前调用,允许开发者检查HTTP请求并决定是否应该继续握手。
    • 可以从HTTP请求中获取当前的HttpSession,并将需要的数据复制到WebSocketSession的属性中。
    • 可以通过修改attributes参数来添加或删除即将传递给WebSocketSession的属性。
    • 如果返回false,则会中断握手,即拒绝建立WebSocket连接。
  • afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Exception exception):

    • 在握手成功完成后调用,无论握手是否成功,都会执行此方法(如果握手失败,则exception参数将包含相关异常)。
    • 通常在此处用于清理资源、记录日志或者进行其他后处理操作。

3.3 WebSocketConfigurer

WebSocketConfigurer 是 Spring Framework 中用于配置 WebSocket 功能的接口,它允许开发者自定义 WebSocket 服务端点(endpoint)的行为和路由规则。该接口位于 org.springframework.web.socket.config.annotation 包下,是 Spring WebSocket 支持的核心部分。

在基于 Spring Boot 构建 WebSocket 应用程序时,通过实现 WebSocketConfigurer 接口或使用其子接口如 DelegatingWebSocketMessageBrokerConfiguration 等,可以方便地配置 WebSocket 的核心功能:

  • 注册 WebSocketHandler:

    开发者可以通过实现 WebSocketConfigurer 中的相应方法来注册处理 WebSocket 连接请求的 WebSocketHandler 实例。这些 Handler 负责与客户端进行双向通信,包括消息接收、处理和发送。

  • 配置访问路径:

    可以设置 WebSocket 的入口地址,即客户端通过哪个 URL 建立 WebSocket 连接。

  • 跨域支持:

    配置是否允许来自不同源的 WebSocket 请求,即 CORS (Cross-Origin Resource Sharing) 政策。

  • 定制握手过程:

    添加 HandshakeInterceptor 实例,以便在 WebSocket 握手阶段执行额外的验证逻辑或操作。

  • 会话管理:

    定义如何管理 WebSocketSession,例如设置超时策略等。

四.spring boot代码

4.1继承AbstractWebSocketHandler

@Slf4j
@Component
public class MyWsHandler extends AbstractWebSocketHandler {

    //保存已经链接的用户
    private static Map<String, WsSessionBean> wsSessionBeanMap;

    static {
        wsSessionBeanMap = new ConcurrentHashMap<>();
    }

    /**
     * //建立链接
     * @param session
     * @throws Exception
     */
    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        super.afterConnectionEstablished(session);

        //过去ur中的参数
        URI uri = session.getUri();
        UriComponents components = UriComponentsBuilder.fromUri(uri).build();

        MultiValueMap<String, String> queryParams = components.getQueryParams();
        String userId = queryParams.getFirst("userId");

        WsSessionBean wsSessionBean = new WsSessionBean(Integer.valueOf(userId), session);

        wsSessionBeanMap.put(session.getId(), wsSessionBean);

        log.info("建立链接了。。。。。{}", wsSessionBean);

    }


    //收到消息
    @Override
    public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) throws Exception {
        super.handleMessage(session, message);
        log.info("当前session信息:{}", session);
        log.info("消息是:message:{}", message.getPayload());
        //广播消息===========================自己实现的代码,用来发送消息
        sendMessageToBroadcast(session.getId(), message.getPayload().toString());

    }
/**
     * 发送消息到所有客户端 (广播消息 发给当前用户得所有好友)
     *
     * @param userId      当前用户sessionId
     * @param messageText 当前用户要发送得内容
     */
    public void sendMessageToBroadcast(String userId, String messageText) {
        wsSessionBeanMap.forEach((k, v) -> {
            if (!k.equals(userId)) {//说明要发得对象
                WebSocketSession targetSession = v.getSession();
                if (targetSession != null && targetSession.isOpen()) {
                    TextMessage textMessage = new TextMessage(messageText);
                    try {
                        targetSession.sendMessage(textMessage);
                    } catch (IOException e) {
                        throw new RuntimeException(e);
                    }
                } else {
                    log.info("无法向用户{}发送消息,会话未建立或已关闭", userId);
                }
            }
        });
    }

    /**
     * 传输异常
     *
     * @param session
     * @param exception
     * @throws Exception
     */
    @Override
    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
        super.handleTransportError(session, exception);
        if (session.isOpen()) {
            session.close();
            wsSessionBeanMap.remove(session.getId());
        }
        log.info("传输异常");

    }

    /**
     * 链接关闭
     *
     * @param session
     * @param status
     * @throws Exception
     */
    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        super.afterConnectionClosed(session, status);
        wsSessionBeanMap.remove(session.getId());
        log.info("链接关闭");
    }

    
}

4.2 实现WebSocketConfigurer

@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {

    @Resource
    private MyWsHandler myWsHandler;
    @Bean
    public HandshakeInterceptor httpSessionHandshakeInterceptor() {
        return new HttpSessionHandshakeInterceptor();
    }
    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
        registry.addHandler(myWsHandler,"/myWs1")
                .setAllowedOrigins("*");
    }
}

欢迎大家👍点赞👍 + 👀关注👀 + 🤏收藏🤏 如有不足请指正

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Vuforia+Unity】AR06-空间环境识别功能(AreaTargets)

Vuforia原理:把被识别的物体转成图、立体图、柱形图,3D模型、环境模型,然后模型生成Vuforia数据库-导入Unity-参考模型位置开始摆放数字内容,然后参考模型自动隐藏-发布APP-识别生活中实物-数字内容叠加上去! 不论你是否曾有过相关经验,只要跟随本文的步骤,你就可以成功…

04|事务的隔离级别

数据库的事务隔离越严格,并发副作用越小,但付出的代价也就越大,因为事务隔离实质上就是 使事务在一定程度上“串行化”进行,这显然与“并发”是矛盾的。 同时,不同的应用对读一致性和事务隔离程度的要求也是不同的,比如许多应用对“不可重复 读"和“幻读”并不敏感,可能更…

c++入门学习⑧——模板

目录 前言 基本介绍 什么是模板&#xff1f; 作用 特点 分类 函数模板 语法 使用方式 注意事项 函数模板和普通函数区别 普通函数和函数模板的调用规则 局限性 类模板 语法 类模板的成员函数创建时机 类模板实例化对象 类模板实例化对象做函数参数 类模板成…

堆/堆排序(C/C++)

本篇文章将会较为全面的介绍堆的概念以及实现堆两个重要算法&#xff1a;向上调整算法和向下调整算法。接着实现了堆排序。 若想查看对应位置&#xff0c;可直接按照以下目录进行查看&#xff1a; 目录 1.堆的概念及结构 2.堆的实现 2.1 堆的向上调整算法 2.2 堆的向下调整算法…

【LNMP】云导航项目部署及环境搭建(复杂)

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、项目介绍1.1项目环境架构LNMP1.2项目代码说明 二、项目环境搭建2.1 Nginx安装2.2 php安装2.3 nginx配置和php配置2.3.1 修改nginx文件2.3.2 修改vim /etc/p…

LemonSqueezy

信息收集 # nmap -sn 192.168.1.0/24 -oN live.nmap Starting Nmap 7.94 ( https://nmap.org ) at 2024-02-08 11:22 CST Nmap scan report for 192.168.1.1 Host is up (0.00037s latency). MAC Address: 00:50:56:C0:00:08 (VMware) Nmap scan r…

微信小程序开发(实战案例):本地生活 - 列表页面开发(动态渲染处理)、节流防抖(节流阀应用)

文章目录 本地生活 - 列表页面开发一、将九宫格分类换成navigator组件二、动态设置商品列表页的 title三、动态渲染商品列表页面四、上拉触底加载数据五、添加Loading加载效果六、数据加载节流防抖处理 本地生活 - 列表页面开发 导入我们上次写的 本地生活 - 首页开发的项目 运…

2024年2月16日优雅草蜻蜓API大数据服务中心v1.1.1大更新-UI全新大改版采用最新设计ui·增加心率计算器·退休储蓄计算·贷款还款计算器等数接口

2024年2月16日优雅草蜻蜓API大数据服务中心v1.1.1大更新-UI全新大改版采用最新设计ui增加心率计算器退休储蓄计算贷款还款计算器等数接口 更新日志 前言&#xff1a;本次更新中途跨越了很多个版本&#xff0c;其次本次ui大改版-同步实时发布教程《带9.7k预算的实战项目layuiph…

Git笔记——4

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言 一、操作标签 二、推送标签 三、多人协作一 完成准备工作 协作开发 将内容合并进master 四、多人协作二 协作开发 将内容合并进master 五、解决 git branch -a…

FreeRTOS任务创建过程详解

本篇文章及记录我在学习FreeRTOS中关于任务创建的详细过程的了解。希望我的分享能给你带来不一样的收获。 目录 一、任务创建的相关函数 二、任务初始化函数分析 三、任务堆栈初始化函数 四、添加任务到就绪列表 一、任务创建的相关函数 前面学了任务创建可以使用动态方法或…

C#学习(十四)——垃圾回收、析构与IDisposable

一、何为GC 数据是存储在内存中的&#xff0c;而内存又分为Stack栈内存和Heap堆内存 Stack栈内存Heap堆内存速度快、效率高结构复杂类型、大小有限制对象只能保存简单的数据引用数据类型基础数据类型、值类型- 举个例子 var c new Customer{id: 123,name: "Jack"…

自定义神经网络二之模型训练推理

文章目录 前言模型概念模型是什么&#xff1f;模型参数有哪些神经网络参数案例 为什么要生成模型模型的大小什么是大模型 模型的训练和推理模型训练训练概念训练过程训练过程中的一些概念 模型推理推理概念推理过程 总结 前言 自定义神经网络一之Tensor和神经网络 通过上一篇…

[深度学习]yolov9+deepsort+pyqt5实现目标追踪

【YOLOv9DeepSORTPyQt5追踪介绍】 随着人工智能技术的飞速发展&#xff0c;目标追踪在视频监控、自动驾驶等领域的应用日益广泛。其中&#xff0c;YOLOv9作为先进的目标检测算法&#xff0c;结合DeepSORT多目标追踪算法和PyQt5图形界面库&#xff0c;能够为用户提供高效、直观…

深度学习500问——Chapter01:数学基础

文章目录 前言 1.1 向量和矩阵 1.1.1 标量、向量、矩阵、张量之间的联系 1.1.2 张量与矩阵的区别 1.1.3 矩阵和向量相乘结果 1.1.4 向量和矩阵的范数归纳 1.1.5 如何判断一个矩阵为正定 1.2 导数和偏导数 1.2.1 导数偏导计算 1.2.2 导数和偏导数有什么区别 1.3 特征值和特征向量…

文献阅读:Transformers are Multi-State RNNs

文献阅读&#xff1a;Transformers are Multi-State RNNs 1. 内容简介2. 方法介绍 1. 基础回顾 1. RNN2. Transformer 2. Transformer解构 1. MSRNN2. Transformer 3. TOVA 1. 现有转换策略2. TOVA 3. 实验考察 & 结论 1. 实验设计2. 实验结果 1. LM2. 长文本理解3. 文本生…

(十三)【Jmeter】线程(Threads(Users))之tearDown 线程组

简述 操作路径如下: 作用:在正式测试结束后执行清理操作,如关闭连接、释放资源等。配置:设置清理操作的采样器、执行顺序等参数。使用场景:确保在测试结束后应用程序恢复到正常状态,避免资源泄漏或对其他测试的影响。优点:提供清理操作,确保测试环境的整洁和可重复性…

通天星CMSV6 车载视频监控平台信息泄露漏洞

免责声明&#xff1a;文章来源互联网收集整理&#xff0c;请勿利用文章内的相关技术从事非法测试&#xff0c;由于传播、利用此文所提供的信息或者工具而造成的任何直接或者间接的后果及损失&#xff0c;均由使用者本人负责&#xff0c;所产生的一切不良后果与文章作者无关。该…

元数据思想-打破传统的思维方式

本文已收录公众号(面汤放盐)&#xff1a;元数据思想-打破传统的思维方式 本文是一篇讲解元数据案例的技术文章; 同时也谈论如何对传统 CRUD 进行破局的文章。 元数据思想-打破传统的思维方式 打破传统的思维模式&#xff0c; 跳出固有的认知模型&#xff0c;从更高的视角去理…

社区分享|中华保险基于MeterSphere开展接口自动化测试

中华联合保险集团股份有限公司&#xff08;以下简称为“中华保险”&#xff09;始创于1986年&#xff0c;是全国唯一一家以“中华”冠名的国有控股保险公司。截至2022年12月底&#xff0c;中华保险总资产为1006.06亿元&#xff0c;在全国拥有超过2900个营业网点&#xff0c;员工…

Python入门必学:reverse()和reversed()的区别

Python入门必学&#xff1a;reverse()和reversed()的区别 &#x1f4c5;2024年02月25日 &#x1f308; 个人主页&#xff1a;高斯小哥 &#x1f525; 高质量专栏&#xff1a;Matplotlib之旅&#xff1a;零基础精通数据可视化、Python基础【高质量合集】、PyTorch零基础入门教程…