Spring Boot 集成 WebSocket 的实战案例
1 添加依赖
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
2 编写 WebSocket Handler
创建一个类来处理 WebSocket 连接的生命周期事件(建立、关闭、接收消息、发送错误)。
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.Random;
import java.util.concurrent.CopyOnWriteArraySet;/*** 创建一个类来处理 WebSocket 连接的生命周期事件(建立、关闭、接收消息、发送错误)*/
public class MyTextWebSocketHandler extends TextWebSocketHandler {// 存储所有活跃的会话,用于广播或其他操作private static final CopyOnWriteArraySet<WebSocketSession> sessions = new CopyOnWriteArraySet<>();/*** 连接建立后执行*/@Overridepublic void afterConnectionEstablished(WebSocketSession session) throws Exception {sessions.add(session);System.out.println("WebSocket 连接建立: " + session.getId());session.sendMessage(new TextMessage("欢迎连接到 WebSocket 服务!"));}/*** 接收到客户端消息后执行*/@Overrideprotected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {String payload = message.getPayload();System.out.println("收到消息: " + payload);// 简单地回复客户端session.sendMessage(new TextMessage("服务器已收到: " + payload));session.sendMessage(new TextMessage("处理中..."));// 模拟处理过程(随机等待 2-10s)Thread.sleep(new Random().nextInt(8) * 1000 + 2000);session.sendMessage(new TextMessage("处理完成: " + payload));// 也可以广播给所有客户端// broadcast(new TextMessage("📢 广播: " + payload));}/*** 连接关闭后执行*/@Overridepublic void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {sessions.remove(session);System.out.println("WebSocket 连接关闭: " + session.getId() + ", 状态: " + status);}/*** 发生错误时执行*/@Overridepublic void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {if (session.isOpen()) {session.close();}sessions.remove(session);System.err.println("WebSocket 传输错误: " + exception.getMessage());}/*** 广播消息给所有连接的客户端*/private void broadcast(TextMessage message) {for (WebSocketSession session : sessions) {if (session.isOpen()) {try {session.sendMessage(message);} catch (IOException e) {System.err.println("广播消息失败: " + e.getMessage());}}}}
}
3 编写 WebSocket 配置类
创建一个配置类来启用 WebSocket 功能,并注册一个或多个 WebSocket Endpoint。
@Configuration
@EnableWebSocket // 启用 WebSocket
public class WebSocketConfig implements WebSocketConfigurer {@Overridepublic void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {// 注册一个 WebSocket Handler,并指定它的访问路径// withAllowedOrigins("*") 允许所有来源(实际生产环境应限制)(生产环境应限制为具体域名)registry.addHandler(new MyTextWebSocketHandler(), "/ws/myTextWeb").setAllowedOrigins("*");}
}
4 客户端测试(HTML/JavaScript)
你可以使用一个简单的 HTML 页面和 JavaScript 来连接和测试你的 WebSocket 服务。
测试页位置:src/main/resources/static/websocket_test.html
<!DOCTYPE html>
<html>
<head><title>WebSocket 客户端测试</title><meta charset="utf-8">
</head>
<body><h1>WebSocket 客户端</h1><div id="messages"></div><input type="text" id="inputMessage" placeholder="输入消息">
<button onclick="sendMessage()">发送</button><script>var webSocket;var messagesDiv = document.getElementById('messages');var inputMessage = document.getElementById('inputMessage');// 假设你的 Spring Boot 应用运行在 8080 端口var url = "ws://localhost:8080/ws/myTextWeb";function connect() {// 检查浏览器是否支持 WebSocketif ('WebSocket' in window) {webSocket = new WebSocket(url);} else {messagesDiv.innerHTML += '<p style="color:red;">当前浏览器不支持 WebSocket.</p>';return;}// 连接成功事件webSocket.onopen = function(event) {messagesDiv.innerHTML += '<p style="color:green;"><b>连接成功!</b></p>';};// 接收消息事件webSocket.onmessage = function(event) {messagesDiv.innerHTML += '<p><b>收到:</b> ' + event.data + '</p>';};// 连接关闭事件webSocket.onclose = function(event) {messagesDiv.innerHTML += '<p style="color:red;"><b>连接关闭.</b></p>';};// 发生错误事件webSocket.onerror = function(event) {messagesDiv.innerHTML += '<p style="color:red;"><b>发生错误!</b></p>';};}function sendMessage() {var message = inputMessage.value;if (webSocket && webSocket.readyState === WebSocket.OPEN) {webSocket.send(message);messagesDiv.innerHTML += '<p><b>发送:</b> ' + message + '</p>';inputMessage.value = ''; // 清空输入框} else {messagesDiv.innerHTML += '<p style="color:orange;">连接未建立或已关闭,请先连接.</p>';}}// ==========================================================// 实现回车发送的关键代码// ==========================================================// 监听输入框的键盘抬起事件inputMessage.addEventListener('keyup', function(event) {// 检查按下的键是否是 Enter 键 (现代浏览器推荐 event.key)if (event.key === 'Enter') {// 阻止默认的表单提交等行为event.preventDefault();// 执行发送消息的函数sendMessage();}});// ==========================================================// 页面加载完成后自动连接window.onload = connect;
</script></body>
</html>
测试截图如下: