【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.mzph.cn/news/585967.shtml

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

相关文章

04-获取认证的用户身份信息

存储用户信息的方式 获取用户信息的流程 用户提交账号和密码后,DaoAuthenticationProvider调用UserDetailsService接口实现类的loadUserByUsername()方法,该方法可以接收请求参数username的值,然后根据该值查询用户信息,最后将账号,密码,权限封装到UserDetails对象中并返回给…

HW01—SY系列单点测厚仪 应用于轧钢橡胶、金属、塑料…

关键字&#xff1a;单点测厚仪,HW01—SY测厚仪,常温测厚仪,热轧板测厚仪,非接触测厚仪,橡胶测厚仪,塑料板测厚仪,木板测厚仪, 产品简介&#xff1a; 该系列测厚仪整体采用C型架结构&#xff0c;C型架上安装上下两个对射的激光位移传感器&#xff0c;可测量一个点的厚度尺寸。C型…

杰发科技AC7840——EEPROM初探

0.序 7840和7801的模拟EEPROM使用不太一样 1.现象 按照官方Demo&#xff0c;在这样的配置下&#xff0c;我们看到存储是这样的&#xff08;连续三个数字1 2 3&#xff09;。 使用串口工具的多帧发送功能 看不出多少规律 修改代码后 发现如下规律&#xff1a; 前四个字节是…

信号与线性系统翻转课堂笔记16——离散LTI系统的各类响应

信号与线性系统翻转课堂笔记16——离散LTI系统的各类响应 The Flipped Classroom16 of Signals and Linear Systems 对应教材&#xff1a;《信号与线性系统分析&#xff08;第五版&#xff09;》高等教育出版社&#xff0c;吴大正著 一、要点 &#xff08;1&#xff0c;重点…

Java连接Mysql报错:javax.net.ssl.SSLException: Received fatal alert: internal_error

大致报错日志如下&#xff1a; The last packet successfully received from the server was 11 milliseconds ago. The last packet sent successfully to the server was 10 milliseconds ago.at sun.reflect.GeneratedConstructorAccessor275.newInstance(Unknown Source)…

了解 NSA 关于管理 OSS 和 SBOM 的最新指南

开源软件很容易受到恶意行为者的攻击&#xff0c;但软件材料清单可以帮助减轻威胁。美国国家安全局的指导为管理生态系统奠定了坚实的基础。 软件供应链安全仍然是网络安全和软件行业的一个关键话题&#xff0c;并且有充分的理由&#xff0c;从针对大型软件供应商的持续攻击到…

2023年年终总结 —— 致满载荣誉或满脸惆怅的你

开篇请允许我引用歌曲《西楼儿女》的一句歌词&#xff1a; 陌生的朋友你请听我讲&#xff0c;许多年前我也曾有梦想&#xff0c;想过满载荣誉回到家乡&#xff0c;这肆意的风压弯了海棠。 2023年即将过去&#xff0c;不管你这一年经历了多少&#xff0c;或是职场的得心应手、情…

GBASE南大通用-小内存单机安装GBase 8c分布式数据库实践

* 这种小内存部署方式仅用于分布式数据库个人学习使用&#xff0c;不建议用于其他用途。 随着数据高并发复杂场景业务需求不断增多&#xff0c;信息数据呈现出爆炸式增长、多源多维、数据类型繁复等特征。在这一趋势下&#xff0c;目前分布式数据库因其架构的天然优势&#xf…

Creo各版本安装指南

下载链接 https://pan.baidu.com/s/1VyP0_185mJeBiorlpUJqrQ?pwd0531 1.鼠标右击【Creo10.0(64bit)】压缩包&#xff08;win11及以上系统需先点击“显示更多选项”&#xff09;【解压到 Creo10.0(64bit)】。 ​2.打开解压后的文件夹&#xff0c;鼠标右击【Crack】选择【解压到…

Winform RDLC报表(数据库连接、报表函数使用、动态表头)

文章目录 NuGet安装库数据库连接报表设计报表引用添加报表 数据集设计方法一手动添加方法二——连接数据库添加 关联报表与数据集表格数据与数据集数据设计表格格式、字体设计报表数据字段绑定 Winform 使用报表控件数据库填充数据集从数据库获取与数据源相同字段的数据 动态表…

数据库一般会采取什么样的优化方法?

数据库一般会采取什么样的优化方法&#xff1f; 1、选取适合的字段属性 为了获取更好的性能&#xff0c;可以将表中的字段宽度设得尽可能小。 尽量把字段设置成not null 执行查询的时候&#xff0c;数据库不用去比较null值。 对某些省份或者性别字段&#xff0c;将他们定义为e…

【并发】AtomicInteger很安全

AtomicInteger 简介与常规用法 AtomicInteger 是 Java 中 java.util.concurrent.atomic 包下的一个类。用于实现原子操作的整数。它是一个基于CAS&#xff08;Compare-And-Swap&#xff09;实现的原子整数类。它提供了一系列的原子操作&#xff0c;确保对整数的操作是原子性的&…

golang 图片加水印,字体文件从哪里找

鼠标左键双击此电脑图标在此电脑文本框输入电脑默认字体地址&#xff1a;C:\Windows\Fonts找到需要用到的字体文件&#xff0c;复制到指定文件夹

python企业车辆车货信息平台 s05fw

车货信息平台系统可具体分为货源方、平台方、承运方三部分。其中前端要求包含货源方&#xff1a;发布货源信息、选择承运方、司机服务评价&#xff1b;平台方&#xff1a;账户管理、货主、司机资质审核、聊天功能&#xff1b;承运方&#xff1a;车辆信息上传、个人车主发布车源…

HEX报文协议打包生成工具

本工具可以用于灵活定制各种格式的报文。以下是定制报文中每个字段的说明&#xff1a; isbig&#xff1a;指示报文中的字节顺序是否为大端序&#xff08;Big Endian&#xff09;。如果为true&#xff0c;则表示使用大端序&#xff1b;如果为false&#xff0c;则表示使用小端序…

WorkPlus局域网即时通讯软件的领航者,连接高效协作的利器

在快速发展的商业环境中&#xff0c;高效的内部沟通和协作对于企业的成功至关重要。而局域网即时通讯软件则成为实现内部高效沟通的必备工具。作为一款领航者级别的局域网即时通讯软件&#xff0c;WorkPlus通过卓越的性能和创新的技术&#xff0c;成为了众多企业的首选之一。 W…

ggplot2 | line plot 分组及均值线:聚类后的表达变化趋势图

1. 效果图 2. 预处理及绘图 # 输入数据 > head(dat)Species cid variable value 1 setosa 1 Sepal.Length 5.1 2 setosa 2 Sepal.Length 4.9 3 setosa 3 Sepal.Length 4.7 4 setosa 4 Sepal.Length 4.6 5 setosa 5 Sepal.Length 5.0 6 setos…

selenium模块有哪些用途?

Selenium模块是一个用于Web应用程序测试的模块&#xff0c;具有多种示例用法。以下是一些示例&#xff1a; 1.打开网页并执行一些基本操作&#xff0c;如点击按钮、输入文本等。 定位网页元素并执行操作&#xff0c;例如使用 find_element 方法查找单个元素&#xff0c;使用 f…

2023第三届中国高校大数据挑战赛B题代码

任务已完成&#xff0c;聚类效果很好&#xff08;主要在于数据的处理以及特征工程&#xff09;, 需代码si&#xff0c;yuer有限先到先得。

深度学习 | 基本循环神经网络

1、序列建模 1.1、序列数据 序列数据 —— 时间 不同时间上收集到的数据&#xff0c;描述现象随时间变化的情况。 序列数据 —— 文本 由一串有序的文本组成的序列&#xff0c;需要进行分词。 序列数据 —— 图像 有序图像组成的序列&#xff0c;后一帧图像可能会受前一帧的影响…