【Java】SpringBoot快速整合WebSocket实现客户端服务端相互推送信息

目录

什么是webSocket?

webSocket可以用来做什么?

WebSocket操作类

一:测试客户端向服务端推送消息

1.启动SpringBoot项目

2.打开网站

3.进行测试消息推送

4.后端进行查看测试结果

二:测试服务端向客户端推送消息

1.接口代码

2.使用postman进行调用

3.查看测试结果


什么是webSocket?

        WebSocket是一种在单个TCP连接上进行全双工通信的协议。WebSocket使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。而Http请求只能从客户端请求服务端才能得到响应。在WebSocket API中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。

webSocket可以用来做什么?

        利用双向数据传输的特点可以用来完成很多功能,不需要前端轮询,浪费资源。例如:
聊天功能、数据实时更新和视频弹幕等

webSocket协议
本协议有两部分:握手和数据传输。
握手是基于http协议的。

来自客户端的握手看起来像如下形式:

GET ws://localhost/chat HTTP/1.1
Host: localhost
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key:dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Protocol: chat,superchat
Sec-WebSocket-Version: 13

来自服务器的握手看起来像如下形式


HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept:s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
Sec-WebSocket-Protocol: chat

SpringBoot快速整合WebSocket代码案例:

下面我就使用SpringBoot快速整合WebSocket实现服务端与客户端的相互推送消息;

代码层级结构


maven依赖

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

WebSocket配置类

package com.example.springboot_websocket_demo01;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
@Configuration
public class WebSocketConfig {/***   注入ServerEndpointExporter,*   这个bean会自动注册使用了@ServerEndpoint注解声明的Websocket endpoint*/@Beanpublic ServerEndpointExporter serverEndpointExporter() {return new ServerEndpointExporter();}}

WebSocket操作类

通过该类WebSocket可以进行群推送以及单点推送

package com.example.springboot_websocket_demo01;import jakarta.websocket.*;
import jakarta.websocket.server.PathParam;
import jakarta.websocket.server.ServerEndpoint;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;@Component
@Slf4j
@ServerEndpoint("/websocket/{userId}")  // 接口路径 ws://localhost:8087/webSocket/userId;
public class WebSocket {//与某个客户端的连接会话,需要通过它来给客户端发送数据private Session session;/*** 用户ID*/private String userId;//concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。//虽然@Component默认是单例模式的,但springboot还是会为每个websocket连接初始化一个bean,所以可以用一个静态set保存起来。//  注:底下WebSocket是当前类名private static CopyOnWriteArraySet<WebSocket> webSockets = new CopyOnWriteArraySet<>();// 用来存在线连接用户信息private static ConcurrentHashMap<String, Session> sessionPool = new ConcurrentHashMap<String, Session>();/*** 链接成功调用的方法*/@OnOpenpublic void onOpen(Session session, @PathParam(value = "userId") String userId) {try {this.session = session;this.userId = userId;webSockets.add(this);sessionPool.put(userId, session);log.info("【websocket消息】有新的连接,总数为:" + webSockets.size());} catch (Exception e) {}}/*** 链接关闭调用的方法*/@OnClosepublic void onClose() {try {webSockets.remove(this);sessionPool.remove(this.userId);log.info("【websocket消息】连接断开,总数为:" + webSockets.size());} catch (Exception e) {}}/*** 收到客户端消息后调用的方法** @param message*/@OnMessagepublic void onMessage(String message) {log.info("【websocket消息】收到客户端消息:" + message);}/*** 发送错误时的处理** @param session* @param error*/@OnErrorpublic void onError(Session session, Throwable error) {log.error("用户错误,原因:" + error.getMessage());error.printStackTrace();}// 此为广播消息public void sendAllMessage(String message) {log.info("【websocket消息】广播消息:" + message);for (WebSocket webSocket : webSockets) {try {if (webSocket.session.isOpen()) {webSocket.session.getAsyncRemote().sendText(message);}} catch (Exception e) {e.printStackTrace();}}}// 此为单点消息public void sendOneMessage(String userId, String message) {Session session = sessionPool.get(userId);if (session != null && session.isOpen()) {try {log.info("【websocket消息】 单点消息:" + message);session.getAsyncRemote().sendText(message);} catch (Exception e) {e.printStackTrace();}}}// 此为单点消息(多人)public void sendMoreMessage(String[] userIds, String message) {for (String userId : userIds) {Session session = sessionPool.get(userId);if (session != null && session.isOpen()) {try {log.info("【websocket消息】 单点消息:" + message);session.getAsyncRemote().sendText(message);} catch (Exception e) {e.printStackTrace();}}}}}

注意:WebSocketConfig和WebSocket必须放在同一层级下,否则Websocket扫描不到ServerEndpoint注解。

一:测试客户端向服务端推送消息

1.启动SpringBoot项目

2.打开网站

WebSocket测试 devTest.run

输入

ws://127.0.0.1:8080/websocket/100

进行连接,测试是否连接成功

3.进行测试消息推送

4.后端进行查看测试结果

测试成功,说明客户端可以使用WebSocket对服务端推送消息。

二:测试服务端向客户端推送消息

1.接口代码

package com.example.springboot_websocket_demo01;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
@RequestMapping("/api")
public class YourController {@Autowiredprivate WebSocket webSocket;@PostMapping("/sendNotification")public void sendNotification() {try {// 创建业务消息信息String message = "postman调用接口访问后端服务器存储数据并使用websocket将消息推送给前端客户端";// 全体发送webSocket.sendAllMessage(message);// 单个用户发送 (userId为用户id)String userId = "1";String message1 = "【websocket消息】 单点消息:只发送给id为"+userId+"的用户。";webSocket.sendOneMessage(userId, message1);// 多个用户发送 (userIds为多个用户id,逗号‘,’分隔)String[] userIds = {"1", "2"};String message2 = "【websocket消息】 单点消息:只发送给id为"+userIds.toString()+"的用户。";webSocket.sendMoreMessage(userIds, message2);} catch (Exception e) {// 输出异常信息e.printStackTrace();}}}

2.使用postman进行调用

用来模仿客户端发送消息到后端服务器然后返回给客户端。(其实也可以直接在WebSocket类中的onMessage中直接进行操作,调用sendAllMessage等其他方法进行测试);

3.查看测试结果

WebSocket测试 devTest.run

正常结果为

还有很多测试方法,自己可以去思考,以上对于SpringBoot整合WebSocket来说可以算是一个简单的入门案例了。

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

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

相关文章

48、激活函数 - 梯度消失和梯度爆炸

简单介绍下梯度消失和梯度爆炸,这个不是重点,但是我觉得有必要再深入了解这个概念,以及很多激活函数为什么是可以防止梯度消失的。 梯度消失和梯度爆炸实际上是在神经网络训练过程中经常会遇到的两类问题,这两类问题都与梯度有关。 什么是梯度 在神经网络训练中,梯度是指…

ALSA学习(5)——设备中的alsa

参考博客&#xff1a; https://blog.csdn.net/DroidPhone/article/details/7165482 &#xff08;一下内容基本是原博主的博客转载&#xff09; 文章目录 一、ASOC的由来二、硬件架构三、软件架构四、数据结构五、内核对ASoC的改进 一、ASOC的由来 ASoC–ALSA System on Chip …

08-接口文档管理工具-项目集成knife4j__ev

2、knife4j快速入门 2.1 knife4j介绍 knife4j是为Java MVC框架集成Swagger生成Api文档的增强解决方案,前身是swagger-bootstrap-ui,取名kni4j是希望它能像一把匕首一样小巧,轻量,并且功能强悍! gitee地址&#xff1a;knife4j: Knife4j是一个集Swagger2 和 OpenAPI3为一体的增…

基于图神经网络的动态物化视图管理

本期 Paper Reading 主要介绍了发布于 2023 年 ICDE 的论文《Dynamic Materialized View Management using Graph Neural Network》&#xff0c;该文研究了动态物化视图管理问题&#xff0c;提出了一个基于 GNN 的模型。在真实的数据集上的实验结果表明&#xff0c;取得了更高的…

SPI通信

SPI通信 1、SPI通信概述 SPI(Serial peripheral interface)是一种同步、串行、全双工、总线制、主从工作方式。 有四线控制&#xff1a; SDO——主设备数据输出&#xff0c;从设备数据输入&#xff0c;对于MOSI output slave inputSDI——主设备数据输入&#xff0c;从事设备…

mapboxgl 中给地图添加遮罩蒙版,并不遮罩其中一块区域

文章目录 概要效果预览技术思路技术细节小结 概要 本篇文章主要是给一整块地图添加遮罩层蒙版&#xff0c;但是不遮罩其中一个区域&#xff0c;以反向高亮地区内容。 效果预览 技术思路 这里要实现某个区域反显高亮&#xff0c;需要这个区域的边界json文件&#xff0c;与ech…

CodeWhisperer:编码世界中的声音启迪者

人烟 导语&#xff1a; 在数字化时代&#xff0c;编码已经成为了一种不可或缺的技能。而 CodeWhisperer&#xff08;编码世界中的声音启迪者&#xff09;则以其卓越的技术和深厚的知识为人们带来了独特的启发和指导。本文将介绍 CodeWhisperer 的背景和成就&#xff0c;探讨他是…

在 Android 手机上从SD 卡恢复数据的 6 个有效应用程序

如果您有 Android 设备&#xff0c;您可能会将个人和专业的重要文件保存在设备的 SD 卡上。这些文件包括照片、视频、文档和各种其他类型的文件。您绝对不想丢失这些文件&#xff0c;但当您的 SD 卡损坏时&#xff0c;数据丢失是不可避免的。 幸运的是&#xff0c;您不需要这样…

web等保评测需要实机查看的操作系统、服务器、数据库和应用部分

“等保测评”全称是信息安全等级保护测评。是经公安部认证的具有资质的测评机构&#xff0c;依据国家信息安全等级保护规范规定&#xff0c;受有关单位委托&#xff0c;按照有关管理规范和技术标准&#xff0c;对信息系统安全等级保护状况进行检测评估的活动。 本文陆续将遇到的…

buildadmin实现多级关联下拉效果

文章目录 最终效果开始重新渲染组件编辑渲染完结 最终效果 开始 popupForm.vue代码 <FormItem :label"t(interior.interiorApply.interior_index_id)" type"remoteSelect"v-model"baTable.form.items!.interior_index_id" prop"interi…

12.29最小生成数K算法复习(注意输入输出格式),校园最短路径(通过PRE实现路径输出,以及输入输出格式注意)

7-2 最小生成树-kruskal算法 分数 15 const int maxn 1000; struct edge {int u, v, w; }e[maxn]; int n, m, f[30]; bool cmp(edge a, edge b) {return a.w < b.w; } int find(int x) {if (f[x] x) {return x;}else {f[x] find(f[x]);return f[x];} } //int arr[100…

linux调试笔记

文章目录 基本启动调试与附加进程断点程序运行控制tui模式查看堆栈与变量监视变量多线程调试 扩展自定义跳转命令解析自定义类型禁用动态库自动加载设置源码路径断点时执行命令gdbserver远程调试 gdb脚本QtCreator调试Linux下处理编译、运行时的一些问题undefined symbol问题-n…

大数据Doris(四十六):物化视图查询改写和适用场景

文章目录 物化视图查询改写和适用场景 一、查询改写

在Centos7中利用Shell脚本:实现MySQL的数据备份

目录 自动化备份MySQL 一.备份数据库脚本 1.创建备份目录 2.创建脚本文件 3.新建配置文件&#xff08;连接数据库的配置文件&#xff09; 4.给文件权限(mysql_backup.sh) ​编辑 5.执行命令 (mysql_backup.sh) ​编辑 二.数据库通过备份恢复 1.创建脚…

前端 js 基础(1)

js 结果输出 &#xff08;点击按钮修改文字 &#xff09; <!DOCTYPE html> <html> <head></head><body><h2>Head 中的 JavaScript</h2><p id"demo">一个段落。</p><button type"button" onclic…

腾讯今年的校招薪资。。。

昨天文章&#xff1a;《龙年红包封面的领取步骤&#xff0c;目前每个账号只能领取一个》。 在网上查了一下腾讯今年的校招薪资&#xff0c;这里主要以技术类为主&#xff0c;比如后端&#xff0c;前端&#xff0c;算法等。基本上都是20k以上&#xff0c;最高的看到有一个29k的&…

功能真强大!5个令人惊叹的 Jupyter 黑科技

Jupyter 是一种功能强大的交互式计算环境&#xff0c;被广泛应用于数据分析、机器学习、科学计算等领域。 除了常见的基本功能外&#xff0c;Jupyter还隐藏着许多令人惊叹的黑科技&#xff0c;这些功能可以帮助用户更高效地完成工作&#xff0c;提升工作体验。 在本文中&…

算法训练营Day34(贪心算法)

1005.K次取反后最大化的数组和 1005. K 次取反后最大化的数组和 - 力扣&#xff08;LeetCode&#xff09; 秒了 class Solution {public int largestSumAfterKNegations(int[] nums, int k) {Arrays.sort(nums);// -4 -3 -2 -1 5//-2 -2 0 2 5int last -1;for(int i 0;i<…

Qt+Opencv:人脸检测

话接上一篇&#xff0c;我们仍使用在上篇《QtOpencv&#xff1a;Qt中部署opencv》创建的Qt项目来测试opencv提供的sample。 在正式开始本篇之前&#xff0c;我们先说做一下准备工作&#xff1a; 一、opencv官方文档 学习最权威和最可靠的方式&#xff0c;就是阅读官方文档和…

短说社区运营的使用工具分享(一)

本文是一篇针对短说社区运营的使用工具分享帖&#xff0c;是小编结合日常使用&#xff0c;总结的一些可以帮助网站管理员和运营人员进行日常操作和管理的工具。 1. 想天工作台之运营面板 想天工作台可以将桌面划分不同的类型来辅助办公&#xff0c;我分享下我当前的桌面情况&…