news 2026/9/29 8:40:35

Springboot实现websocket通信

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Springboot实现websocket通信

目录

前言

一、websockt是什么?

Websockt与 HTTP协议的核心区别

二、后端代码实现

三、前端代码实现

总结


前言

本文目标springboot实现websocket通信并且实现聊天功能。


一、websockt是什么?

WebSocket 是一种在单个 TCP 连接上实现全双工通信的网络协议,旨在解决传统 HTTP 协议在实时通信场景中的局限性。

Websockt与 HTTP协议的核心区别

HTTP 是单向、无状态的请求 - 响应协议:

  • 客户端必须主动发起请求,服务端才能响应,服务端无法主动向客户端推送数据;
  • 每次请求都需要建立新的 TCP 连接(HTTP/1.1 虽支持长连接,但仍需客户端主动发起请求)。

而 WebSocket 实现了双向、持久的实时通信:

  • 一旦连接建立,客户端和服务端可随时互相发送数据,无需频繁发起请求;
  • 连接建立后保持持久,直到某一方主动关闭,大幅降低了连接开销。

二、后端代码实现

编写websocket配置类。

@Configuration public class WebSocketConfiguration { @Bean public ServerEndpointExporter serverEndpointExporter(){ return new ServerEndpointExporter(); } }

编写websocket实现类。

@Component @ServerEndpoint("/ws/{id}") public class WebSocket { private static Map<String, Session> sessionMap = new HashMap<>(); @OnOpen public void onOpen(Session session){ Map<String, List<String>> parameters = session.getRequestParameterMap(); String token = parameters.get("token").get(0); String id = TokenUtil.webSocketGetUser(token).getId().toString(); sessionMap.put(id,session); System.err.println(id); } @OnMessage public void onMessage(String message,@PathParam("id") String id,Session session){ Map<String, List<String>> parameters = session.getRequestParameterMap(); //获取用户连接集合 String token = parameters.get("token").get(0); //通过路径携带参数获取接收者id Integer id1 = TokenUtil.webSocketGetUser(token).getId(); //通过token获取用户id System.out.println("收到来自客户端"+"的信息"+message+"发给"+id); sendToOneClient(id,message); } @OnClose public void onClose(Session session){ Map<String, List<String>> parameters = session.getRequestParameterMap(); String token = parameters.get("token").get(0); String id = TokenUtil.webSocketGetUser(token).getId().toString(); sessionMap.remove(id); } public void sendToOneClient(String id,String message) { Session session1 = sessionMap.get(id); try { session1.getBasicRemote().sendText(message); } catch (Exception e){ e.printStackTrace(); } } public static void sendToAllClient(String message) { Collection<Session> sessions = sessionMap.values(); for (Session session : sessions) { try { session.getBasicRemote().sendText(message); } catch (Exception e){ e.printStackTrace(); } } } }

该实现类中接口地址:ws://xxx/ws/{id},xxx是服务(后端)的地址加上端口号,前端连接时url 参数带上 token,如:ws://127.0.0.1:8080/ws/接收方id?token=xxx。其中,id可以是任何用于区分接收方的值。

接下来介绍该实现类中的主要部分:

首先,sessionMap是静态 Map,该实例全局共享。其中,key = 用户 id 字符串,value = 当前用户的 webSocket 会话 session。它的作用是保存所有在线用户,并用来定向发消息。

接下来是几个方法的详细讲解:

@OnOpen注解的函数在客户端建立连接时触发。当客户端和该服务建立连接时,先获取客户端带过来的用户token,通过token解析用户信息(这里获取用户id,在用户登录时生成token需要使用用户id生成),随后把可以识别用户唯一标识的信息存入sessionMap。即表示该用户在线。

@OnMessage注解的函数在收到客户端消息时触发。形参中的 message 为消息内容,因此可以获取到发送人id、接收人id以及发送消息内容三样东西,可以形成一个两人聊天的闭环。其中,@PathParam("id") String id 用来获取路径中所传递的接收方id。

@OnClose注解的函数在客户端断开连接时触发。当客户端关闭 ws 连接时,解析当前用户会话的session和对应的token,并拿到用户 id,从 sessionMap 移除该 session,表示该用户下线。

最后,就是两个发送消息的函数:

第一个是 sendToOneClient,接收的参数分别为接收方id和消息内容。使用接收方id便可以在 sessionMap 中找到接收方的会话 session。调用该session的getBasicRemote().sendText() 方法就可以实现把消息发送给接收方。但是在这一步,如果接收方不在线,即 sessionMap 中没有该用户的 session,那么消息将无法送达。因此,可以在这一步之前添加其它业务的代码,如将对应的消息内容、发送方id、接收方id以及发送时间保存至数据库,实现接收方用户登录时可以查看到所收到的所有消息。

第二个是 sendToAllClient,接收的参数为消息内容。该函数会先遍历 sessionMap,随后对sessionMap 中所有的 session (所有在线用户)发送对应的消息内容。

以上是websocket的后端实现,更多的玩法,如群聊等等都可以在这些基础功能函数上进行拓展。

三、前端代码实现

代码如下:

// 替换成你的后端地址,200是接收方id const ws = new WebSocket('ws://127.0.0.1:8080/ws/200?token=xxx'); //连接创建时调用的函数 ws.onopen = function() { console.log('连接成功'); } //收到消息时调用的函数 ws.onmessage = function(e) { console.log('收到消息:', e.data); } //连接关闭时调用的函数 ws.onclose = function() { console.log('连接关闭'); } // 捕获连接过程中的异常 ws.onerror = function(err) { console.error('错误', err); } //向接收方发送消息时调用的函数 function send() { const val = document.getElementById('msg').value; ws.send(val); }

这段 JS 代码创建 WebSocket 实例,连接地址中指定接收方 id与身份 token。ws.onopen在 WebSocket 成功建立连接时触发,打印连接成功日志;ws.onmessage用于监听后端推送过来的消息;ws.onclose在连接关闭时执行,输出关闭日志;ws.onerror捕获连接过程中的异常并打印错误信息;自定义 send 函数读取输入框内容,通过 ws.send 把消息内容发送给后端。


总结

本文实现了前后端的 websocket 通信。希望对未来的架构师们有帮助~

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/29 8:40:06

Keil C51与MDK共存:一套uVision5搞定51和STM32开发

我自己最早是从Keil C51开始接触单片机的&#xff0c;后来转做STM32&#xff0c;在很长一段时间里&#xff0c;我的电脑上同时装着两个Keil&#xff0c;每次换项目都得到开始菜单里翻半天图标&#xff0c;烦得不行。后来才发现&#xff0c;Keil本身就支持在同一台机器、同一个u…

作者头像 李华
网站建设 2026/9/29 8:36:44

BOM管理:制造企业降本增效的“隐形冠军”,你真的用对了吗?

在制造业这片江湖里&#xff0c;如果说图纸是产品的灵魂&#xff0c;那么物料清单&#xff08;Bill of Materials&#xff0c;简称BOM&#xff09;就是产品的骨架。它不仅仅是一份简单的清单&#xff0c;更是串联设计、采购、生产、销售的核心纽带。很多时候&#xff0c;企业面…

作者头像 李华
网站建设 2026/9/29 8:36:06

零成本高效写代码:TaoToken 统一 Key 接入 VS Code AI 编程工具实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/29 8:32:41

TensorFlow 2.x实战指南:从环境配置到模型部署的完整笔记

聊点实在的。我接触TensorFlow差不多有六年了&#xff0c;从1.4时代的静态图&#xff0c;一路折腾到2.x的Keras默认工作流&#xff0c;中间踩过的坑比踩过的门槛还多。前阵子还有学生在问&#xff1a;2024年了&#xff0c;还有必要学TensorFlow吗&#xff1f;PyTorch不是更火吗…

作者头像 李华