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

前言

👏作者简介:我是笑霸final,一名热爱技术的在校学生。

📝个人主页:个人主页1 || 笑霸final的主页2

📕系列专栏:java专栏

📧如果文章知识点有错误的地方,请指正!和大家一起学习,一起进步👀

🔥如果感觉博主的文章还不错的话,👍点赞👍 + 👀关注👀 + 🤏收藏🤏

目录

一.环境准备

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

xml 复制代码
 	<dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-websocket</artifactId>
    </dependency>

二.vue代码

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

1、创建stores/demo.ts

js 复制代码
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 }
})

二、在使用的组件中使用

javascript 复制代码
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

javascript 复制代码
@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

javascript 复制代码
@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("*");
    }
}

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

相关推荐
Moshow郑锴1 小时前
SpringBootCodeGenerator使用JSqlParser解析DDL CREATE SQL 语句
spring boot·后端·sql
小沈同学呀7 小时前
创建一个Spring Boot Starter风格的Basic认证SDK
java·spring boot·后端
凤山老林9 小时前
SpringBoot 轻量级一站式日志可视化与JVM监控
jvm·spring boot·后端
郝亚军10 小时前
websocket 服务器往客户端发送的数据要加掩码覆盖吗?
服务器·网络·websocket
Chan1610 小时前
JVM从入门到实战:从字节码组成、类生命周期到双亲委派及打破双亲委派机制
java·jvm·spring boot·后端·intellij-idea
科兴第一吴彦祖12 小时前
在线会议系统是一个基于Vue3 + Spring Boot的现代化在线会议管理平台,集成了视频会议、实时聊天、AI智能助手等多项先进技术。
java·vue.js·人工智能·spring boot·推荐算法
练习时长一年15 小时前
搭建langchain4j+SpringBoot的Ai项目
java·spring boot·后端
Rysxt_15 小时前
Spring Boot 集成 Spring AI OpenAI Starter 教程
java·spring boot·后端·ai
吃饭最爱15 小时前
⽹络请求Axios的概念和作用
vue