Spring Boot 3 整合 WebSocket (STOMP协议) 和 Vue 3 实现实时通信

🚀 作者主页: 有来技术
🔥 开源项目: youlai-mall 🍃 vue3-element-admin 🍃 youlai-boot
🌺 仓库主页: Gitee 💫 Github 💫 GitCode
💖 欢迎点赞 👍 收藏 ⭐留言 📝 如有错误敬请纠正!

topic

目录

  • 引言
  • 核心概念
    • 什么是 WebSocket ?
    • 什么是 STOMP ?
    • STOMP On Spring WebSocket
  • WebSocket 服务端(SpringBoot3)
    • 添加依赖
    • WebSocket 配置类
    • WebSocket 监听和发送
  • WebSocket 客户端(Vue3)
    • 安装依赖
    • WebSocket 客户端连接
    • WebSocket 客户端订阅
    • WebSocket 客户端推送
  • WebSocket 测试
    • WebSocket 连接测试
    • WebSocket 广播测试
    • WebSocket 点对点测试
  • 项目源码
  • 结语

引言

WebSocket是一种在Web浏览器与Web服务器之间建立双向通信的协议,而Spring Boot提供了便捷的WebSocket支持。本篇博客将介绍如何在Spring Boot 3中整合WebSocket,并使用Vue 3构建简单而强大的实时通信应用。

核心概念

什么是 WebSocket ?

WebSocket是一种在单个TCP连接上提供全双工通信的协议,允许客户端和服务器之间实时双向通信,无需客户端发起请求。其优势在于低延迟和高效率,适用于即时通讯、在线游戏、实时协作编辑等场景。

什么是 STOMP ?

STOMP 官网: 官方文档 | 中文文档

STOMP是一种基于文本的消息传递协议,用于实现消息传递系统之间的互操作性。它简单、跨语言、适应性强,支持多种消息传递模式。通常与WebSocket结合,提供浏览器和服务器之间的实时双向通信。

STOMP是一种简单的消息传递协议,初衷是为脚本语言(如 Ruby、 Python 和 Perl)和web框架创建一种基于文本的简单异步消息协议。相比于正式诞生于2011年的WebSocket,STOMP在此之前广泛使用了十年以上,并且得到了很多客户端(如stomp.js、Gozirra、stomp.py、stompngo等)、消息代理端(如ActiveMQ、RabbitMQ等)、工具库的支持,目前最新的协议版本为2012年1.2版本。

具体来说,STOMP是一种基于Frame的协议,每个Frame由一个命令Command、一组Headers和可选的正文Body组成,如下是一个STOMP frame的基本结构示例:

SEND   //作为COMMAND
Authorization:Bearer xxx        //作为Headers
content-type:application/json   //作为HeadersHello World!  //消息内容,可以多行,直到^@为止  //作为Body
^@ //此Frame结束

STOMP On Spring WebSocket

spring-framework #websocket-stomp

Spring Framework 从 4.0.0 加入了spring-websocket 和 spring-messaging 两大模块。

从Spring文档的篇幅、提供的应用样例以及spring-boot-starter-websocket直接引入了spring-websocket 和 spring-messaging模块(包含了STOMP等相关内容)等各种情况,不难看出基于STOMP做为其消息交互协议的方式,是spring主推的完整的websocket解决方案即 STOMP On Spring WebSocket,即使用STOMP也是spring框架的选择。

WebSocket 服务端(SpringBoot3)

添加依赖

首先,在pom.xml中添加WebSocket依赖:

<!-- WebSocket依赖 -->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId>
</dependency>

WebSocket 配置类

配置 WebSocket 支持实时双向通信和消息传递,使用STOMP协议。提供连接端点 “/ws”,支持跨域WebSocket连接,配置消息代理实现广播和点对点推送。

package com.youlai.system.config;/*** WebSocket 配置** @author haoxr* @since 2.4.0*/
@Configuration
@EnableWebSocketMessageBroker // 启用WebSocket消息代理功能和配置STOMP协议,实现实时双向通信和消息传递
@RequiredArgsConstructor
@Slf4j
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {private final JwtTokenProvider jwtTokenProvider;/*** 注册一个端点,客户端通过这个端点进行连接*/@Overridepublic void registerStompEndpoints(StompEndpointRegistry registry) {registry.addEndpoint("/ws")   // 注册了一个 /ws 的端点.setAllowedOriginPatterns("*") // 允许跨域的 WebSocket 连接.withSockJS();  // 启用 SockJS (浏览器不支持WebSocket,SockJS 将会提供兼容性支持)}/*** 配置消息代理*/@Overridepublic void configureMessageBroker(MessageBrokerRegistry registry) {// 客户端发送消息的请求前缀registry.setApplicationDestinationPrefixes("/app");// 客户端订阅消息的请求前缀,topic一般用于广播推送,queue用于点对点推送registry.enableSimpleBroker("/topic", "/queue");// 服务端通知客户端的前缀,可以不设置,默认为userregistry.setUserDestinationPrefix("/user");}/*** 配置客户端入站通道拦截器* <p>* 添加 ChannelInterceptor 拦截器,用于在消息发送前,从请求头中获取 token 并解析出用户信息(username),用于点对点发送消息给指定用户** @param registration 通道注册器*/@Overridepublic void configureClientInboundChannel(ChannelRegistration registration) {registration.interceptors(new ChannelInterceptor() {@Overridepublic Message<?> preSend(Message<?> message, MessageChannel channel) {StompHeaderAccessor accessor = MessageHeaderAccessor.getAccessor(message, StompHeaderAccessor.class);// 如果是连接请求(CONNECT 命令),从请求头中取出 token 并设置到认证信息中if (accessor != null && StompCommand.CONNECT.equals(accessor.getCommand())) {// 从连接头中提取授权令牌String bearerToken = accessor.getFirstNativeHeader(HttpHeaders.AUTHORIZATION);// 验证令牌格式并提取用户信息if (StrUtil.isNotBlank(bearerToken) && bearerToken.startsWith("Bearer ")) {try {// 移除 "Bearer " 前缀,从令牌中提取用户信息(username), 并设置到认证信息中String tokenWithoutPrefix = bearerToken.substring(7);String username = jwtTokenProvider.getUsername(tokenWithoutPrefix);if (StrUtil.isNotBlank(username)) {accessor.setUser(() -> username);return message;}} catch (Exception e) {log.error("Failed to process authentication token.", e);}}}// 不是连接请求,直接放行return ChannelInterceptor.super.preSend(message, channel);}});}
}

WebSocket 监听和发送

package com.youlai.system.controller;import com.youlai.system.model.dto.ChatMessage;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.messaging.handler.annotation.DestinationVariable;
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import java.security.Principal;/*** WebSocket 测试控制器** @author haoxr* @since 2.3.0*/
@RestController
@RequestMapping("/websocket")
@RequiredArgsConstructor
@Slf4j
public class WebsocketController {private final SimpMessagingTemplate messagingTemplate;/*** 广播发送消息** @param message 消息内容*/@MessageMapping("/sendToAll")@SendTo("/topic/notice")public String sendToAll(String message) {return "服务端通知: " + message;}/*** 点对点发送消息* <p>* 模拟 张三 给 李四 发送消息场景** @param principal 当前用户* @param username  接收消息的用户* @param message   消息内容*/@MessageMapping("/sendToUser/{username}")public void sendToUser(Principal principal, @DestinationVariable String username, String message) {String sender = principal.getName(); // 发送人String receiver = username; // 接收人log.info("发送人:{}; 接收人:{}", sender, receiver);// 发送消息给指定用户 /user/{username}/queue/greetingmessagingTemplate.convertAndSendToUser(receiver, "/queue/greeting", new ChatMessage(sender, message));}
}

WebSocket 客户端(Vue3)

安装依赖

# WebSocket 客户端和类型定义
npm i sockjs-client  
npm i -D @types/sockjs-client
# STOMP 协议的 JavaScript 客户端和类型定义
npm i stompjs
npm i -D @types/stompjs
# net 是 Node核心模块之一,用于创建 TCP 服务器和客户端模块
npm i net -S

WebSocket 客户端连接

下面是 Websocket 连接部分关键代码,完整代码:websocket.vue

<!-- websocket 示例 -->
<script setup lang="ts">
import SockJS from "sockjs-client";
import Stomp from "stompjs";import { useUserStoreHook } from "@/store/modules/user";const userStore = useUserStoreHook(); // websocket 连接传递 tokenconst isConnected = ref(false);
const socketEndpoint = ref("http://localhost:8989/ws"); let stompClient: Stomp.Client;
/*** 连接*/
function connect() {let socket = new SockJS(socketEndpoint.value);stompClient = Stomp.over(socket);stompClient.connect({ Authorization: userStore.token },() => {console.log("连接成功");},(error) => {console.log("连接失败: " + error);});
}
/*** 断开连接*/
function disconnect() {if (stompClient && stompClient.connected) {stompClient.disconnect(() => {console.log("断开连接");});}
}onMounted(() => {connect();
});
</script>

WebSocket 客户端订阅

下面是 Websocket 订阅部分关键代码,完整代码:websocket.vue

stompClient.subscribe("/topic/notice", (res: any) => {console.log("订阅广播成功:" + res.body);
});stompClient.subscribe("/user/queue/greeting", (res) => {console.log("订阅点对点成功:" + res.body);
});
  • /topic/notice

    对应服务端广播队列

    image-20231214155237181

  • /user/queue/greeting

    对应服务端点对点队列,其中 /user/ 前缀是 WebSocketConfig 里通过 registry.setUserDestinationPrefix("/user") 设定的服务端通知客户端的前缀。

WebSocket 客户端推送

下面是 Websocket 订阅部分关键代码,完整代码:websocket.vue


function sendToAll() {stompClient.send("/app/sendToAll", {},  "亲爱的大冤种们,由于一只史诗级的BUG,系统版本已经被迫回退到了0.0.1。");console.log("广播消息发送成功");	
}function sendToUser() {stompClient.send("/app/sendToUser/root", {}, "嗨! root 我是 admin ,想和您交个朋友");console.log("点对点消息发送成功");	
}
  • /app/sendToAll

    客户端发送的目标地址,指定服务端 @MessageMapping("/sendToAll") 方法处理此消息

    其中 /app 是 WebSocketConfig 里通过 registry.setApplicationDestinationPrefixes("/app") 设定的客户端发送目标地址的前缀

  • /app/sendToUser/root

    对应服务端处理消息的方法如下:

WebSocket 测试

在线测试地址: vue3-element-admin#websocket

WebSocket 连接测试

WebSocket 广播测试

topic

WebSocket 点对点测试

项目源码

GithubGitee
后端youlai-boot 🍃youlai-boot 🍃
前端vue3-element-admin 🌺vue3-element-admin 🌺

结语

本文深入介绍了在Spring Boot 3中整合WebSocket及Vue 3构建实时通信应用。选择STOMP协议,配置服务端、客户端,实现连接、消息广播和点对点推送。通过在线测试验证整合效果,包括连接、广播和点对点消息。希望读者通过这个实例更好地理解WebSocket在Spring Boot中的应用。

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

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

相关文章

家政服务小程序预约上门,让服务更便捷

随着人们生活节奏的加快&#xff0c;家政服务行业越来越受到人们的欢迎。为了满足市场需求&#xff0c;提高服务质量&#xff0c;家政公司需要开发一款预约上门的家政服务小程序。本文将详细介绍如何制作一个预约上门的家政服务小程序。 一、登录乔拓云网后台 首先&#xff0c…

基于vue实现的疫情数据可视化分析及预测系统-计算机毕业设计推荐django

目 录 摘 要 I ABSTRACT II 目 录 II 第1章 绪论 1 1.1背景及意义 1 1.2 国内外研究概况 1 1.3 研究的内容 1 第2章 相关技术 3 2.1 nodejs简介 4 2.2 express框架介绍 6 2.4 MySQL数据库 4 第3章 系统分析 5 3.1 需求分析 5 3.2 系统可行性分析 5 3.2.1技术可行性&#xff1a;…

Appium自动化常用adb操作封装

一、前置说明 在Appium自动化中&#xff0c;经常需要使用adb命令与设备进行交互&#xff0c;所以有必要把常用的adb操作封装成一个类 二、代码实现 import os import platform import re import subprocessfrom common import path from common.exception import AndroidSDK…

语音识别功能测试:90%问题,可以通过技术解决

现在市面上的智能电子产品千千万&#xff0c;为了达到人们使用更加方便的目的&#xff0c;很多智能产品都开发了语音识别功能&#xff0c;用来语音唤醒进行交互&#xff1b;另外&#xff0c;各大公司也开发出来了各种智能语音机器人&#xff0c;比如小米公司的“小爱”&#xf…

DHCP—动态主机配置协议

动态主机配置协议DHCP&#xff08;Dynamic Host Configuration Protocol&#xff0c;动态主机配置协议&#xff09;是RFC 1541&#xff08;已被RFC 2131取代&#xff09;定义的标准协议&#xff0c;该协议允许服务器向客户端动态分配IP地址和配置信息。 DHCP协议支持C/S&#x…

外汇天眼:Coinbase国际交易所将启动现货市场

Coinbase宣布了Coinbase国际交易所扩张的下一阶段——退出符合条件客户的非美国现货市场。 这一最新发展旨在满足Coinbase全球用户群体的独特需求和需求&#xff0c;同时强化其扩大国际访问可信产品和服务的战略使命。 Coinbase国际交易所现货交易的推出和扩展将分阶段进行。1…

vite+vue3+electron搭建项目

编辑器使用vscode&#xff0c;打开一个空文件夹 第一步 初始化vite项目 初始化vite项目&#xff0c;命令 npm init vite 第二步 下载依赖 进入新建的项目&#xff0c;下载依赖&#xff0c;命令 cd vite-projec npm i第三步 使用cnpm下载 electron依赖 新建一个终端&#…

05 python数据容器

5.1 数据容器认识 5.2 python列表 5.2.1 列表的定义 演示数据容器之&#xff1a;list 语法&#xff1a;[元素&#xff0c;元素&#xff0c;....] #定义一个列表List List [itheima,uityu,gsdfg] List1 [itheima,6666,True] print(List) print(List1) print(type(List)) pr…

综合实验:期末

实验要求&#xff1a; 一&#xff0e;物理连接 实验分2个组进行&#xff0c;使用思科模拟软件。每个同学模拟两个组。每个组选用一台路由器、一台三层交换机和一台二层交换机。要求按下图拓扑进行连接。如下图&#xff1a;最上端设备为核心交换机&#xff0c;按老师要求配置&a…

实验:BGP配置

1.实验目的&#xff1a; 本实验旨在掌握BGP协议的基本概念和配置方法&#xff0c;以及使用Packet Tracer模拟网络环境进行BGP配置的方法。 2.实验要求&#xff1a; 理解BGP协议的基本概念和原理&#xff1b;掌握BGP协议的配置方法&#xff1b;能够使用Packet Tracer模拟网络…

2019年第八届数学建模国际赛小美赛B题数据中心冷出风口的设计解题全过程文档及程序

2019年第八届数学建模国际赛小美赛 B题 数据中心冷出风口的设计 原题再现&#xff1a; 这是数据中心空调设计面临的一个问题。在一些数据中心&#xff0c;计算机机柜是开放的&#xff0c;在一个房间里排列成三到四排。冷却后的空气通过主管进入房间&#xff0c;并分为三到四个…

华为交换机——配置策略路由(基于IP地址)示例

一、组网需求&#xff1a; 汇聚层Switch做三层转发设备&#xff0c;接入层设备LSW做用户网关&#xff0c;接入层LSW和汇聚层Switch之间路由可达。汇聚层Switch通过两条链路连接到两个核心路由器上&#xff0c;一条是高速链路&#xff0c;网关为10.1.20.1/24&#xff1b;另外一…

【Hive】——DDL(DATABASE)

1 概述 2 创建数据库 create database if not exists test_database comment "this is my first db" with dbproperties (createdByAllen);3 描述数据库信息 describe 可以简写为desc extended 可以展示更多信息 describe database test_database; describe databa…

案例058:基于微信小程序的智能社区服务管理系统

文末获取源码 开发语言&#xff1a;Java 框架&#xff1a;SSM JDK版本&#xff1a;JDK1.8 数据库&#xff1a;mysql 5.7 开发软件&#xff1a;eclipse/myeclipse/idea Maven包&#xff1a;Maven3.5.4 小程序框架&#xff1a;uniapp 小程序开发软件&#xff1a;HBuilder X 小程序…

C++类与对象(一)

目录 一&#xff0c;面向过程和面向对象初步认识 二&#xff0c;类的引入 三&#xff0c;类的定义 四&#xff0c;类的访问限定符及封装 五&#xff0c;类的实例化 六&#xff0c;类对象模型 七&#xff0c;this指针 一&#xff0c;面向过程和面向对象初步认识 c语言是面…

超聚变服务器(原华为服务器)网站模拟器

一、超聚变服务器&#xff08;原华为服务器&#xff09;网站模拟器&#xff1a; 原来了解服务器可以从他的网站上进行了解&#xff0c;模拟器做的很好了。 https://support.xfusion.com/server-simulators/ 有很多的模拟器&#xff0c;今天主要看下BMC的设置 有很多的在线工具…

软考机考考试第一批经验分享

由于机考的特殊性&#xff0c;考试环境与传统笔试环境有所不同。下面是与考试环境相关的总结&#xff1a; 草稿纸&#xff1a;考场提供足够数量的草稿纸&#xff0c;每位考生都会分发一张白纸作为草稿纸。在草稿纸上需要写上准考证号。如果不够用&#xff0c;可以向监考老师再次…

java springboot+jsoup写一段爬虫脚本 将指定地址的 图片链接 文本 超链接地址存入自己的属性类对象中

首先 还是最基本的 要在 pom.xml 引入依赖 <dependency><groupId>org.jsoup</groupId><artifactId>jsoup</artifactId><version>1.14.1</version> </dependency>然后 我们可以在项目中创建一个属性类 我这里就叫 WebContent了…

自己动手写数据库: select 查询语句对应查询树的构造和执行

首先我们需要给原来代码打个补丁&#xff0c;在SelectScan 结构体初始化时需要传入 UpdateScan 接口对象&#xff0c;但很多时候我们需要传入的是 Scan 对象&#xff0c;因此我们需要做一个转换&#xff0c;也就是当初始化 SelectScan 时&#xff0c;如果传入的是 Scan 对象&am…

JWT令牌的作用和生成

JWT令牌&#xff08;JSON Web Token&#xff09;是一种用于身份验证和授权的安全令牌。它由三部分组成&#xff1a;头部、载荷和签名。 JWT令牌的作用如下&#xff1a; 身份验证&#xff1a;JWT令牌可以验证用户身份。当用户登录后&#xff0c;服务器会生成一个JWT令牌并返回…