SpringBoot3-整合WebSocket指南

server/2025/1/19 8:38:57/

更多SpringBoot3内容请关注我的专栏:《SpringBoot3》
期待您的点赞??收藏评论

SpringBoot3-整合WebSocket指南
  • 1. 什么是WebSocket?
  • 2. 环境准备
    • 2.1 项目依赖
  • 3. WebSocket配置
    • 3.1 WebSocket配置类
    • 3.2 自定义WebSocket处理器
  • 4. 控制器
  • 5. 前端实现
    • 5.1 HTML页面
  • 6. 测试WebSocket功能
  • 7. 进阶功能
    • 7.1 心跳检测
    • 7.2 消息重试机制
  • 8. 注意事项
  • 9. 总结
  • 参考资料

1. 什么是WebSocket

WebSocket 是一种网络通信协议,提供全双工通信通道,使服务器可以主动向客户端推送数据。与传统的 HTTP 请求-响应模式不同,WebSocket 在建立连接后,允许服务器和客户端之间进行双向实时通信。

主要特点:

  • 建立在 TCP 协议之上
  • 与 HTTP 协议有良好的兼容性
  • 数据格式轻量,性能开销小
  • 可以发送文本和二进制数据
  • 没有同源限制,客户端可以与任意服务器通信

2. 环境准备

2.1 项目依赖

首先在pom.xml中添加必要的依赖:

<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>3.2.5</version>
</parent><dependencies><!-- WebSocket依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId></dependency><!-- Web依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- Lombok依赖(可选) --><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency>
</dependencies>

image-20241215200948577

3. WebSocket配置

3.1 WebSocket配置类

创建 WebSocket 配置类,启用 WebSocket 功能并注册端点:

package com.coderjia.boot3websocket.config;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;/*** @author CoderJia* @create 2024/12/15 下午 08:11* @Description**/
@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {@Overridepublic void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {registry.addHandler(webSocketHandler(), "/websocket").setAllowedOrigins("*"); // 允许跨域访问}@Beanpublic WebSocketHandler webSocketHandler() {// 使用自定义的WebSocket处理器return new CustomWebSocketHandler();}
}

3.2 自定义WebSocket处理器

创建自定义的 WebSocket 处理器,处理消息收发:

package com.coderjia.boot3websocket.config;import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;/*** @author CoderJia* @create 2024/12/15 下午 08:21* @Description**/
@Component
@Slf4j
public class CustomWebSocketHandler extends TextWebSocketHandler {// 用于存储WebSocket会话private final Map<String, WebSocketSession> sessions = new ConcurrentHashMap<>();@Overridepublic void afterConnectionEstablished(WebSocketSession session) throws Exception {String sessionId = session.getId();sessions.put(sessionId, session);log.info("WebSocket连接建立成功:{}", sessionId);}@Overrideprotected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {String payload = message.getPayload();log.info("收到消息:{}", payload);// 发送回复消息String replyMessage = "服务器收到消息:" + payload;session.sendMessage(new TextMessage(replyMessage));}@Overridepublic void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {String sessionId = session.getId();sessions.remove(sessionId);log.info("WebSocket连接关闭:{}", sessionId);}@Overridepublic void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {log.error("WebSocket传输错误", exception);}// 广播消息给所有连接的客户端public void broadcastMessage(String message) {sessions.values().forEach(session -> {try {session.sendMessage(new TextMessage(message));} catch (IOException e) {log.error("广播消息失败", e);}});}
}

4. 控制器

创建 REST 控制器,用于测试消息广播:

@RestController
@RequestMapping("/api/websocket")
public class WebSocketController {private final CustomWebSocketHandler webSocketHandler;public WebSocketController(CustomWebSocketHandler webSocketHandler) {this.webSocketHandler = webSocketHandler;}@PostMapping("/broadcast")public ResponseEntity<String> broadcastMessage(@RequestBody String message) {webSocketHandler.broadcastMessage(message);return ResponseEntity.ok("消息广播成功");}
}

5. 前端实现

5.1 HTML页面

<!DOCTYPE html>
<html lang="en">
<head><title>WebSocket测试</title>
</head>
<body><div><h2>WebSocket测试页面</h2><div><input type="text" id="messageInput" placeholder="输入消息"><button onclick="sendMessage()">发送</button></div><div id="messages" style="margin-top: 20px;"></div></div><script>let ws = null;function connect() {ws = new WebSocket('ws://localhost:8080/websocket');ws.onopen = function() {console.log('WebSocket连接已建立');appendMessage('系统消息:连接已建立');};ws.onmessage = function(event) {appendMessage('收到消息:' + event.data);};ws.onclose = function() {console.log('WebSocket连接已关闭');appendMessage('系统消息:连接已关闭');};ws.onerror = function(error) {console.error('WebSocket错误:', error);appendMessage('系统消息:连接发生错误');};}function sendMessage() {const messageInput = document.getElementById('messageInput');const message = messageInput.value;if (ws && message) {ws.send(message);appendMessage('发送消息:' + message);messageInput.value = '';}}function appendMessage(message) {const messagesDiv = document.getElementById('messages');const messageElement = document.createElement('div');messageElement.textContent = message;messagesDiv.appendChild(messageElement);}// 页面加载完成后连接WebSocketwindow.onload = connect;</script>
</body>
</html>

6. 测试WebSocket功能

  1. 启动 SpringBoot 应用

  2. 打开多个浏览器窗口访问 HTML 页面

  3. 在任意窗口发送消息,观察其他窗口是否收到消息

  4. 使用 POST 请求测试广播功能:

    curl -X POST http://localhost:8080/api/websocket/broadcast
    -H “Content-Type: text/plain”
    -d “这是一条广播消息”

连接

HTML页面

测接口

广播

7. 进阶功能

7.1 心跳检测

为了保持WebSocket连接的稳定性,可以实现心跳机制:

    @Scheduled(fixedRate = 10000) // 每10秒发送一次心跳,需要启动类或配置类上添加@EnableSchedulingpublic void sendHeartbeat() {String heartbeat = "heartbeat";sessions.values().forEach(session -> {try {session.sendMessage(new TextMessage(heartbeat));} catch (IOException e) {log.error("发送心跳消息失败", e);}});}

心跳

7.2 消息重试机制

当消息发送失败时,实现重试机制:

public void sendMessageWithRetry(WebSocketSession session, String message, int maxRetries) {int retryCount = 0;while (retryCount < maxRetries) {try {session.sendMessage(new TextMessage(message));return;} catch (IOException e) {retryCount++;log.error("消息发送失败,尝试重试 {}/{}", retryCount, maxRetries);try {Thread.sleep(1000);} catch (InterruptedException ie) {Thread.currentThread().interrupt();break;}}}log.error("消息发送失败,达到最大重试次数");
}

8. 注意事项

  1. 连接管理

    • 及时清理断开的连接
    • 实现最大连接数限制
    • 考虑使用连接池管理WebSocket连接
  2. 安全性

    • 实现用户认证
    • 添加消息加密
    • 设置适当的跨域策略
  3. 性能优化

    • 使用消息队列处理大量消息
    • 实现消息压缩
    • 控制消息大小
  4. 错误处理

    • 完善异常处理机制
    • 实现日志记录
    • 添加监控告警

9. 总结

SpringBoot 3 整合 WebSocket 提供了一种高效的实时通信解决方案。通过本文的配置和示例,你可以快速实现:

  • WebSocket服务器端配置
  • 客户端连接管理
  • 消息收发处理
  • 广播功能
  • 心跳检测
  • 错误处理

这些功能可以作为构建实时应用的基础,如在线聊天、实时数据推送、游戏等场景。根据具体需求,你可以在此基础上扩展更多功能。

参考资料

  • Spring WebSocket文档
  • WebSocket协议规范
  • Spring Boot文档

http://www.ppmy.cn/server/159579.html

相关文章

Linux——动静态库

库的本质实际上就是已经写好的&#xff0c;现有的、可以被复用的代码的集合。库被分为两类&#xff0c;一类是静态库&#xff1a;.a[Linux]、.lib[windows]&#xff1b;一类是&#xff1a;动态库&#xff1a;.so[Linux]、.dll[Windows]。其实这里就会有疑问&#xff0c;为什么我…

【PowerQuery专栏】PowerQuery的函数Excel.WorkBook

对于Excel文件来说,目前有两种不同场景需要使用到Excel函数进行解析: 当前Excel数据解析 Excel.CurrentWorkbook外部引用Excel数据解析 Excel.Workbook这里先来看一下当前Excel当前文件数据的引用,Excel.CurrentWorkbook 是基于当前的Excel中的表对象进行数据…

从零搭建SpringBoot3+Vue3前后端分离项目基座,中小项目可用

文章目录 1. 后端项目搭建 1.1 环境准备1.2 数据表准备1.3 SpringBoot3项目创建1.4 MySql环境整合&#xff0c;使用druid连接池1.5 整合mybatis-plus 1.5.1 引入mybatis-plus1.5.2 配置代码生成器1.5.3 配置分页插件 1.6 整合swagger3&#xff08;knife4j&#xff09; 1.6.1 整…

mongodb详解二:基础操作

基础操作 数据库操作collection操作查看表插入数据查找数据 数据库操作 1.创建数据库 use test_db;如果没有数据库&#xff0c;use命令会新建一个&#xff1b;有的话&#xff0c;会切换到这个数据库 2.查看数据库 show dbs;collection操作 查看表 show tables;插入数据 …

“AI 自动化效能评估系统:开启企业高效发展新征程

在当今数字化飞速发展的时代&#xff0c;企业面临着日益激烈的市场竞争&#xff0c;如何提升效率、降低成本成为了企业生存与发展的关键。AI 自动化效能评估系统应运而生&#xff0c;它如同一把智能钥匙&#xff0c;为企业开启了高效发展的新征程。 AI 自动化效能评估系统&…

【Kotlin】上手学习之类型篇

一、类型 1.1 基本类型 主要分为 数字及其无符号版布尔字符字符串数组 1.1.1 数字 整数类型 Kotlin 提供了一组表示数字的内置类型。 对于整数&#xff0c;有四种不同大小的类型&#xff0c;因此值的范围也不同&#xff1a; 类型大小&#xff08;比特数&#xff09;最小…

题解 CodeForces 430B Balls Game 栈 C/C++

题目传送门&#xff1a; Problem - B - Codeforceshttps://mirror.codeforces.com/contest/430/problem/B翻译&#xff1a; Iahub正在为国际信息学奥林匹克竞赛&#xff08;IOI&#xff09;做准备。有什么比玩一个类似祖玛的游戏更好的训练方法呢&#xff1f; 一排中有n个球…

微服务容器化部署好处多吗?

微服务容器化部署好处有很多&#xff0c;包括环境一致性、资源高效利用、快速部署与启动、隔离性与安全性、版本控制与回滚以及持续集成与持续部署。这些优势助力应用可靠稳定运行&#xff0c;提升开发运维效率&#xff0c;是现代软件架构的优质选择。UU云小编认为微服务容器化…