【Springboot系列】SpringBoot整合WebSocket,既然如此简单(含源码)

文章目录

      • 前言:
      • 什么是WebSocket?
      • Spring Boot中的WebSocket支持
      • WebSocket和HTTP优劣势
        • WebSocket的优势:
          • 1.实时性:
          • 2.较低的延迟:
          • 3.较小的数据传输量:
          • 4.更好的兼容性:
        • HTTP的优势:
          • 1.简单易用:
          • 2.更广泛的应用:
          • 3.更好的安全性:
      • 示例
        • 版本依赖
        • 代码
          • WebSocketConfig
          • WebSocketServer
          • WebSocketController
          • webSocket.html
        • 测试
          • 打开2个页面
          • 都点击开启socket
          • 都点击发送
      • 总结
      • 源码获取
      • 写在最后

579a429daf314744b995f37351b46548

前言:

在当今互联网时代,实时通信已经成为了许多应用程序的基本需求。

而WebSocket作为一种全双工通信协议,为开发者提供了一种简单、高效的实时通信解决方案。

本文将介绍如何使用Spring Boot框架来实现WebSocket的集成,快速搭建实时通信功能。


什么是WebSocket?

WebSocket是一种在单个TCP连接上进行全双工通信的协议。与传统的HTTP请求-响应模式不同,WebSocket允许服务器主动向客户端推送数据,实现了实时通信的功能。WebSocket协议基于HTTP协议,通过在握手阶段升级协议,使得服务器和客户端可以直接进行数据交换,而无需频繁的HTTP请求。


Spring Boot中的WebSocket支持

Spring Boot提供了对WebSocket的支持,通过集成Spring WebSocket模块,我们可以轻松地实现WebSocket功能。在Spring Boot中,我们可以使用注解来定义WebSocket的处理器和消息处理方法,从而实现实时通信。


WebSocket和HTTP优劣势

image-20231127012922773

WebSocket的优势:
1.实时性:

​ WebSocket是一种全双工通信协议,可以实现服务器主动向客户端推送数据,实现实时通信。相比之下,HTTP是一种请求-响应模式 的协议,需要客户端主动发起请求才能获取数据。

2.较低的延迟:

​ 由于WebSocket使用单个TCP连接进行通信,避免了HTTP的握手和头部信息的重复传输,因此具有较低的延迟。

3.较小的数据传输量:

​ WebSocket使用二进制数据帧进行传输,相比于HTTP的文本数据传输,可以减少数据传输量,提高传输效率。

4.更好的兼容性:

​ WebSocket协议可以在多种浏览器和平台上使用,具有较好的兼容性。

HTTP的优势:
1.简单易用:

​ HTTP是一种简单的请求-响应协议,易于理解和使用。相比之下,WebSocket需要进行握手和协议升级等复杂操作。

2.更广泛的应用:

​ HTTP协议广泛应用于Web开发中,支持各种类型的请求和响应,可以用于传输文本、图片、视频等多种数据格式。

3.更好的安全性:

​ HTTP协议支持HTTPS加密传输,可以保证数据的安全性。

综上,WebSocket适用于需要实时通信和较低延迟的场景,而HTTP适用于传输各种类型的数据和简单的请求-响应模式。在实际应用中,可以根据具体需求选择合适的协议。


示例

版本依赖
模块版本
SpringBoot3.1.0
JDK17
代码
WebSocketConfig
@Configuration
public class WebSocketConfig {@Beanpublic ServerEndpointExporter serverEndpointExporter() {return new ServerEndpointExporter();}
}
WebSocketServer
@Component
@ServerEndpoint("/server/{uid}")
@Slf4j
public class WebSocketServer {/*** 记录当前在线连接数*/private static int onlineCount = 0;/*** 使用线程安全的ConcurrentHashMap来存放每个客户端对应的WebSocket对象*/private static ConcurrentHashMap<String, WebSocketServer> webSocketMap = new ConcurrentHashMap<>();/*** 与某个客户端的连接会话,需要通过它来给客户端发送数据*/private Session session;/*** 接收客户端消息的uid*/private String uid = "";/*** 连接建立成功调用的方法* @param session* @param uid*/@OnOpenpublic void onOpen(Session session, @PathParam("uid") String uid) {this.session = session;this.uid = uid;if (webSocketMap.containsKey(uid)) {webSocketMap.remove(uid);//加入到set中webSocketMap.put(uid, this);} else {//加入set中webSocketMap.put(uid, this);//在线数加1addOnlineCount();}log.info("用户【" + uid + "】连接成功,当前在线人数为:" + getOnlineCount());try {sendMsg("连接成功");} catch (IOException e) {log.error("用户【" + uid + "】网络异常!", e);}}/*** 连接关闭调用的方法*/@OnClosepublic void onClose() {if (webSocketMap.containsKey(uid)) {webSocketMap.remove(uid);//从set中删除subOnlineCount();}log.info("用户【" + uid + "】退出,当前在线人数为:" + getOnlineCount());}/*** 收到客户端消息后调用的方法* @param message 客户端发送过来的消息* @param session 会话*/@OnMessagepublic void onMessage(String message, Session session) {log.info("用户【" + uid + "】发送报文:" + message);//群发消息//消息保存到数据库或者redisif (StringUtils.isNotBlank(message)) {try {//解析发送的报文ObjectMapper objectMapper = new ObjectMapper();Map<String, String> map = objectMapper.readValue(message, new TypeReference<Map<String, String>>(){});//追加发送人(防止串改)map.put("fromUID", this.uid);String toUID = map.get("toUID");//传送给对应的toUserId用户的WebSocketif (StringUtils.isNotBlank(toUID) && webSocketMap.containsKey(toUID)) {webSocketMap.get(toUID).sendMsg(objectMapper.writeValueAsString(map));} else {//若果不在这个服务器上,可以考虑发送到mysql或者redislog.error("请求目标用户【" + toUID + "】不在该服务器上");}} catch (Exception e) {log.error("用户【" + uid + "】发送消息异常!", e);}}}/*** 处理错误* @param session* @param error*/@OnErrorpublic void onError(Session session, Throwable error) {log.error("用户【" + this.uid + "】处理消息错误,原因:" + error.getMessage());error.printStackTrace();}/*** 实现服务器主动推送* @param msg* @throws IOException*/private void sendMsg(String msg) throws IOException {this.session.getBasicRemote().sendText(msg);}/*** 发送自定义消息* @param message* @param uid* @throws IOException*/public static void sendInfo(String message, @PathParam("uid") String uid) throws IOException {log.info("发送消息到用户【" + uid + "】发送的报文:" + message);if (!StringUtils.isEmpty(uid) && webSocketMap.containsKey(uid)) {webSocketMap.get(uid).sendMsg(message);} else {log.error("用户【" + uid + "】不在线!");}}private static synchronized int getOnlineCount() {return onlineCount;}private static synchronized void addOnlineCount() {WebSocketServer.onlineCount++;}private static synchronized void subOnlineCount() {WebSocketServer.onlineCount--;}}
WebSocketController
@RestController
public class WebSocketController {@GetMapping("/page")public ModelAndView page() {return new ModelAndView("webSocket");}@RequestMapping("/push/{toUID}")public ResponseEntity<String> pushToClient(String message, @PathVariable String toUID) throws Exception {WebSocketServer.sendInfo(message, toUID);return ResponseEntity.ok("Send Success!");}
}
webSocket.html
<!DOCTYPE html>
<html>
<head><meta charset="utf-8"><title>WebSocket消息通知</title>
</head>
<script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.js"></script>
<script>var socket;//打开WebSocketfunction openSocket() {if (typeof (WebSocket) === "undefined") {console.log("您的浏览器不支持WebSocket");} else {console.log("您的浏览器支持WebSocket");//实现化WebSocket对象,指定要连接的服务器地址与端口,建立连接.var socketUrl = "http://localhost:8080/socket/server/" + $("#uid").val();//将https与http协议替换为ws协议socketUrl = socketUrl.replace("https", "ws").replace("http", "ws");console.log(socketUrl);if (socket != null) {socket.close();socket = null;}socket = new WebSocket(socketUrl);//打开事件socket.onopen = function () {console.log("WebSocket已打开");//socket.send("这是来自客户端的消息" + location.href + new Date());};//获得消息事件socket.onmessage = function (msg) {console.log(msg.data);//发现消息进入,开始处理前端触发逻辑};//关闭事件socket.onclose = function () {console.log("WebSocket已关闭");};//发生了错误事件socket.onerror = function () {console.log("WebSocket发生了错误");}}}//发送消息function sendMessage() {if (typeof (WebSocket) === "undefined") {console.log("您的浏览器不支持WebSocket");} else {console.log("您的浏览器支持WebSocket");console.log('{"toUID":"' + $("#toUID").val() + '","Msg":"' + $("#msg").val() + '"}');socket.send('{"toUID":"' + $("#toUID").val() + '","Msg":"' + $("#msg").val() + '"}');}}
</script>
<body>
<p>【uid】:
<div><input id="uid" name="uid" type="text" value="1"></div>
<p>【toUID】:
<div><input id="toUID" name="toUID" type="text" value="2"></div>
<p>【Msg】:
<div><input id="msg" name="msg" type="text" value="hello WebSocket2"></div>
<p>【第一步操作:】:
<div><button onclick="openSocket()">开启socket</button>
</div>
<p>【第二步操作:】:
<div><button onclick="sendMessage()">发送消息</button>
</div>
</body></html>
测试
打开2个页面

第一个:

http://localhost:8080/socket/page

image-20231127013642997

第二个:

http://localhost:8080/socket/page

image-20231127013737748

都点击开启socket

image-20231127013910603

都点击发送

image-20231127014019027

至此示例发送完成


总结

通过本文的介绍,我们了解了Spring Boot中如何集成WebSocket,实现实时通信的功能。

WebSocket作为一种高效的实时通信协议,为开发者提供了更好的用户体验和交互性。

希望本文能够帮助快速掌握Spring Boot整合WebSocket的方法,为应用程序添加实时通信功能。


源码获取

如果需要完整源码请关注公众号"架构殿堂" ,回复 "SpringBoot+WebSocket"即可获得


写在最后

感谢您的支持和鼓励! 😊🙏

如果大家对相关文章感兴趣,可以关注公众号"架构殿堂",会持续更新AIGC,java基础面试题, netty, spring boot, spring cloud等系列文章,一系列干货随时送达!

csdn-end

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

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

相关文章

教师如何高质量备课

备课是教学工作中不可或缺的一部分。高质量的备课不仅可以提高课堂效率&#xff0c;还可以更好地激发学生的学习兴趣和积极性。那么&#xff0c;如何高质量备课呢&#xff1f; 深入了解学生 备课的目的是教授知识&#xff0c;让学生掌握知识。因此&#xff0c;了解学生的需求和…

「直播预告」替代 Oracle,我们还有多长的路要走?

数字经济浪潮席卷全球&#xff0c;我国数字经济也进入快速发展阶段&#xff0c;作为数字化重要载体&#xff0c;国产软件的重要性不言而喻。近年来&#xff0c;国际局势复杂多变&#xff0c;在客观要求和主观需求的双重驱动下&#xff0c;核心技术自主可控的紧迫性也愈加凸显。…

​使用PotPlayer播放器查看软解和硬解4K高清视频时的CPU及GPU占用情况​

目录 1、问题说明 2、PotPlayer播放器介绍 3、视频的软解与硬解 4、使用PotPlayer查看4K高清视频软解和硬解时的CPU占用情况 4.1、使用软解时CPU和GPU占用情况 4.2、使用硬解时CPU和GPU占用情况 5、最后 VC常用功能开发汇总&#xff08;专栏文章列表&#xff0c;欢迎订阅…

学嵌入式,已经会用stm32做各种小东西了,下一步是什么

学嵌入式&#xff0c;已经会用stm32做各种小东西了&#xff0c;下一步是什么&#xff0c;研究stm32的内部吗&#xff1f; 针对题主这种类型的&#xff0c;首先我想提出几个技术问题。 1&#xff0c;除了那几个常用的外设&#xff0c;stm32上集成的众多外设是否都有实际的使用经…

Day58权限提升-网站权限后台漏洞第三方获取

webshell 一般我们的渗透流程就是信息收集&#xff0c;发现漏洞&#xff0c;漏洞利用&#xff0c;一些漏洞成功之后获得一些相应的权限&#xff0c;还有一些是漏洞利用成功之后并没有取得的权限&#xff0c;而这个权限是要通过漏洞利用之后在利用其它地方取货的权限。 权限的获…

百度人工智能培训第二天笔记

参加了百度人工智能初步培训&#xff0c;主要是了解一下现在人工智能的基本情况&#xff0c;以便后续看可以参与一些啥&#xff1f; 下面就继续前一天的内容记录。 一、先做电动自行车的电梯里检测 先进行图片资料的上传与标注&#xff0c;这个昨天的最好也说了一下。 训练完后…

sql中的left join, right join 和inner join,union 与union all的用法

left join&#xff0c; right join 和inner join&#xff1a;这些都是SQL中用来连接两个或多个表的操作。 union&#xff0c;union all&#xff1a;用于合并两个或多个 SELECT 语句的结果。 但是有时候&#xff0c;对于Select出来的结果集不是很清楚。 假设我们有两张表。pers…

让CHAT简单说明下软件工程师的工作性质

问CHAT&#xff1a;软件工程师的工作性质是什么&#xff1f; CHAT回复&#xff1a;软件工程师的工作性质主要包括以下几点&#xff1a; 1. 解决问题&#xff1a;软件工程师的很大一部分工作就是解决问题&#xff0c;这可能是来自客户的特定需求&#xff0c;也可能是软件开发过…

现货黄金走势图下载与保存

MetaTrader 4 (MT4) 是一款在全球范围内广受欢迎的现货黄金交易软件&#xff0c;简单性和灵活性是其深受市场欢迎的原因。它的显示界面的主要部分由品种的走势图表组成&#xff0c;投资者可以在其中查看实时的行情走势。屏幕左上角是市场观察窗口&#xff0c;当中列出了平台所有…

NABOCUL集团专注科研创新 为内源护肤、护发提供更优选择

据权威媒体报道,日本知名化妆品集团NABOCUL Cosmetics株式会社研通过多年的科技创新和内源护肤研究,创新研发Olandu、TakuMin、“CIMIVOSOTUY”等核心成分,向中国消费者传递“关爱恒久之美”的理念,更好地释放内源护肤的独特魅力,为人们内源护肤、护发提供了全新选择。 据了解,…

JVM中的双亲委派模型

双亲委派模型&#xff08;Parent-Delegation Model&#xff09;是Java类加载器&#xff08;ClassLoader&#xff09;机制的一种实现方式。它是Java中实现类加载的一种层次结构模型。 双亲委派模型的工作过程是&#xff1a;在Java中&#xff0c;每个类加载器实例都有一个父类加载…

多头注意力机制基本概念

文章目录 基本概念模型小结 基本概念 我们可以用独立学习得到的h组不同的 线性投影来变换查询、键和值。 然后&#xff0c;这h组变换后的查询、键和值将并行地送到注意力汇聚中。 最后&#xff0c;将这h个注意力汇聚的输出拼接在一起&#xff0c; 并且通过另一个可以学习的线性…

Keil报错_Error:CreateProcess failed,Command:‘xxx\fromelf.exe‘

1、报错信息 2、分析及解决 错误原因&#xff1a;fromelf.exe路径错误&#xff0c;无法执行命令。 发生情景&#xff1a;编译从另一个电脑拷贝的代码时。 解决方法&#xff1a; 1、当你不需要生成bin文件时&#xff0c;可以选择不执行这个命令。&#xff08;去掉√&#xf…

每日一练2023.11.27———连续因子【PTA】

题目要求&#xff1a; 一个正整数 N 的因子中可能存在若干连续的数字。例如 630 可以分解为 3567&#xff0c;其中 5、6、7 就是 3 个连续的数字。给定任一正整数 N&#xff0c;要求编写程序求出最长连续因子的个数&#xff0c;并输出最小的连续因子序列。 输入格式&#xff…

百度智能云正式上线Python SDK版本并全面开源

文章目录 前言一、SDK的优势二、千帆SDK&#xff1a;快速落地LLM应用三、如何快速上手千帆SDK3.1、SDK快速启动3.2. SDK进阶指引 3.3. 通过Langchain接入千帆SDK4、开源社区 前言 百度智能云千帆大模型平台再次升级&#xff01;在原有API基础上&#xff0c;百度智能云正式上线…

Jenkins Pipeline应用实践

Jenkins Pipeline是一种可编程的、可扩展的持续交付管道&#xff0c;允许您使用脚本来定义整个软件交付过程。 以下是使用Jenkins Pipeline创建和配置流水线的基本步骤。 Part 01. 创建一个Pipeline Job 在Jenkins中创建一个新的"Pipeline"类型的Job。 以下是在Je…

跨境电商与物联网:智能设备的未来

随着科技的不断发展&#xff0c;跨境电商和物联网的结合呈现出前所未有的新格局。在这个数字化的时代&#xff0c;智能设备正成为跨境电商的新宠&#xff0c;为商业、物流和消费者带来了全新的体验。本文将深入探讨跨境电商与物联网的结合&#xff0c;探讨智能设备在未来的发展…

为什么制定交易策略要根据资金量,澳福一个例子说清楚

为什么制定交易策略要根据资金量。其实很简单&#xff0c;澳福一个例子说清楚。 假如投资者现在有一大笔资金&#xff0c;就可以用这笔资金的1个百分点的利息来支付自己的日常开支&#xff0c;一百万的1%利息就足够了&#xff0c;可以支付你想要的一切。澳福和各位投资者是不是…

【axios】拦截器:axios.interceptors.request.use|axios.interceptors.response.use

文章目录 概述设置拦截器Axios 拦截器的实现任务注册任务编排任务调度 来源 概述 axios有请求拦截器&#xff08;request&#xff09;、响应拦截器&#xff08;response&#xff09;、axios自定义回调处理&#xff08;这里就是我们常用的地方&#xff0c;会将成功和失败的回调…

成为一名优秀教师的关键要素

在教育领域&#xff0c;要想成为一名优秀的教师可是需要多方面的素质和技能的。以下是我总结出的几点关键要素&#xff0c;供大家参考。 热爱教育事业 首先对教育事业充满热爱和热情。只有对事业有强烈的兴趣和热爱&#xff0c;才能在漫长的工作中保持耐心、专注和投入。热爱教…