基于SpringBoot WebSocket模块实现消息的即时推送
前言
在现代Web应用中,实时消息推送已经成为基础需求。相比传统的轮询方式,WebSocket提供了真正的全双工通信能力。本文将演示如何在SpringBoot中通过集成WebSocket来实现服务端向前端推送通知消息。
一、WebSocket简介
WebSocket 是一种在单个 TCP 连接上进行全双工通信的协议。它使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。WebSocket 的出现解决了传统 HTTP 协议在实时通信方面的不足,广泛应用于实时聊天、在线游戏、股票行情推送等场景。
1. WebSocket 的核心特点
- 全双工通信:客户端和服务端可以同时发送和接收数据,无需等待对方响应。
- 低延迟:避免了传统 HTTP 协议中频繁的请求-响应开销,显著降低延迟。
- 节省带宽:WebSocket 使用帧格式传输数据,比传统的 HTTP 请求更高效,节省了带宽
- 简化开发:WebSocket 提供了简单的 API,使得开发实时应用变得更加容易。
- 跨域支持:需服务端配置 Origin 白名单。
2. WebSocket 与其他技术对比
技术 实时性 资源消耗 兼容性 适用场景 WebSocket 高 中等 较好 实时通知、聊天 HTTP轮询 低(延迟高) 高 极好 简单状态更新 长轮询 中等 中等 较好 小型实时应用 Server-Sent Events (SSE) 单向推送 低 较好 单向通知 3. WebSocket 的局限性
- 复杂性:比 RESTful API 更难调试和维护。
- 兼容性:部分老旧浏览器不支持 WebSocket。
- 资源消耗:长时间保持连接可能增加服务器负载,会话过多导致内存泄露。
- 分布式环境:会话分散问题、消息同步问题、状态一致性问题。
- 安全性:需额外配置(如 WSS 加密)以防止中间人攻击。
二、WebSocket后台实现
1. 环境准备
组件 版本 JDK >=17 Spring Boot 3.x Maven 3.9.9 2. 添加pom依赖
引入spring-boot-starter-web、spring-boot-starter-websocket两个依赖
org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-websocket
spring-boot-starter-web:快速构建web应用、支持restful服务、内嵌servlet容器如tomcat等。
spring-boot-starter-websocket:提供WebSocket的支持。
3. 添加配置类
package com.example.websocket.config; import com.example.websocket.handler.MyWebSocketHandler; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.socket.config.annotation.EnableWebSocket; import org.springframework.web.socket.config.annotation.WebSocketConfigurer; import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry; @Configuration @EnableWebSocket public class WebSocketConfig implements WebSocketConfigurer { @Override public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { registry.addHandler(notificationHandler(), "/ws/notifications") .setAllowedOriginPatterns("*"); } @Bean public MyWebSocketHandler notificationHandler() { return new MyWebSocketHandler(); } }
@EnableWebSocket注解启用原生 WebSocket功能。
registerWebSocketHandlers方法主要干了两件事,一是配置websocket访问端点 ws://localhost:8080/ws/notifications。二是跨域问题处理,*允许所有域访问,也可以指定具体域名,并支持通配符。
4. 添加消息处理类
package com.example.websocket.handler; 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.concurrent.CopyOnWriteArrayList; public class MyWebSocketHandler extends TextWebSocketHandler { private final CopyOnWriteArrayList sessions = new CopyOnWriteArrayList(); @Override public void afterConnectionEstablished(WebSocketSession session) { sessions.add(session); System.out.println("客户端连接成功: " + session.getId()); } @Override protected void handleTextMessage(WebSocketSession session, TextMessage message) { // 处理客户端发来的消息(可选) String payload = message.getPayload(); System.out.println("收到客户端消息: " + payload); } @Override public void afterConnectionClosed(WebSocketSession session, CloseStatus status) { sessions.remove(session); System.out.println("客户端断开连接: " + session.getId()); } // 向单个客户端发送消息 private void sendMessage(WebSocketSession session, String message) { try { if (session.isOpen()) { session.sendMessage(new TextMessage(message)); } } catch (IOException e) { e.printStackTrace(); } } // 向所有客户端广播消息 public void broadcast(String message) { sessions.forEach(session -> sendMessage(session, message)); } }
TextWebSocketHandler:处理文本消息的核心类,可重写方法,处理连接建立、关闭、错误等事件。
- afterConnectionEstablished:连接成功时触发。
- afterConnectionClosed:连接关闭时触发。
- handleTransportError:传输错误时触发。
- handleTextMessage:处理客户端发送的数据。
BinaryWebSocketHandler:处理二进制数据如图片、文件等。
5. 添加controller模拟发送数据
package com.example.websocket.controller; import com.example.websocket.handler.MyWebSocketHandler; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class MessageController { @Autowired private MyWebSocketHandler simpleWebSocketHandler; @GetMapping("/msg") public void sendMsg() { simpleWebSocketHandler.broadcast("您有新的订单,请及时查收"); } }
三、WebSocket前台实现
1. 环境准备
组件 版本 Node.js v22.14.0 Vue 3.5.13 Vite 6.2.0 2. 创建Vue项目
npm create vite@latest vue3-websocket --template vue
3. 创建Websocket.vue文件
Connection Status: {{ isConnected ? 'Connected' : 'Disconnected' }}Send5. 启动并运行
控制台执行npm run dev
四、总结
本文详细介绍了SpringBoot集成WebSocket模块并结合前端Vue3来实现消息的即时推送的过程。虽然使用WebSocket实现消息推送很简单,但是生产环境应需结合项目实际情况,综合考虑以下因素以确保系统的稳定性、可扩展性和可维护性。
❗ 内存压力:WebSocket会话信息都保持在了JVM中,当客户端连接数量非常大时,会导致服务端内存和 CPU 压力激增。
❗消息广播和同步:集群模式部署应用时,多个客户端分散在不同后端节点上,单个节点无法直接推送消息给其他节点连接的客户端。
❗ Nginx配置与长连接限制:Nginx默认配置可能断开空闲WebSocket连接,负载均衡策略(如轮询)可能导致频繁重连,影响消息实时性。