SpringBoot3整合WebSocket詳細指南
1. 什么是WebSocket?
WebSocket 是一種網(wǎng)絡(luò)通信協(xié)議,提供全雙工通信通道,使服務(wù)器可以主動向客戶端推送數(shù)據(jù)。與傳統(tǒng)的 HTTP 請求-響應(yīng)模式不同,WebSocket 在建立連接后,允許服務(wù)器和客戶端之間進行雙向?qū)崟r通信。
主要特點:
- 建立在 TCP 協(xié)議之上
- 與 HTTP 協(xié)議有良好的兼容性
- 數(shù)據(jù)格式輕量,性能開銷小
- 可以發(fā)送文本和二進制數(shù)據(jù)
- 沒有同源限制,客戶端可以與任意服務(wù)器通信
2. 環(huán)境準備
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>
3. WebSocket配置
3.1 WebSocket配置類
創(chuàng)建 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 { @Override public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { registry.addHandler(webSocketHandler(), "/websocket") .setAllowedOrigins("*"); // 允許跨域訪問 } @Bean public WebSocketHandler webSocketHandler() { // 使用自定義的WebSocket處理器 return new CustomWebSocketHandler(); } }
3.2 自定義WebSocket處理器
創(chuàng)建自定義的 WebSocket 處理器,處理消息收發(fā):
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<>(); @Override public void afterConnectionEstablished(WebSocketSession session) throws Exception { String sessionId = session.getId(); sessions.put(sessionId, session); log.info("WebSocket連接建立成功:{}", sessionId); } @Override protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception { String payload = message.getPayload(); log.info("收到消息:{}", payload); // 發(fā)送回復(fù)消息 String replyMessage = "服務(wù)器收到消息:" + payload; session.sendMessage(new TextMessage(replyMessage)); } @Override public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception { String sessionId = session.getId(); sessions.remove(sessionId); log.info("WebSocket連接關(guān)閉:{}", sessionId); } @Override public 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. 控制器
創(chuàng)建 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. 前端實現(xiàn)
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()">發(fā)送</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('系統(tǒng)消息:連接已建立'); }; ws.onmessage = function(event) { appendMessage('收到消息:' + event.data); }; ws.onclose = function() { console.log('WebSocket連接已關(guān)閉'); appendMessage('系統(tǒng)消息:連接已關(guān)閉'); }; ws.onerror = function(error) { console.error('WebSocket錯誤:', error); appendMessage('系統(tǒng)消息:連接發(fā)生錯誤'); }; } function sendMessage() { const messageInput = document.getElementById('messageInput'); const message = messageInput.value; if (ws && message) { ws.send(message); appendMessage('發(fā)送消息:' + message); messageInput.value = ''; } } function appendMessage(message) { const messagesDiv = document.getElementById('messages'); const messageElement = document.createElement('div'); messageElement.textContent = message; messagesDiv.appendChild(messageElement); } // 頁面加載完成后連接WebSocket window.onload = connect; </script> </body> </html>
6. 測試WebSocket功能
- 啟動 SpringBoot 應(yīng)用
- 打開多個瀏覽器窗口訪問 HTML 頁面
- 在任意窗口發(fā)送消息,觀察其他窗口是否收到消息
- 使用 POST 請求測試廣播功能:
curl -X POST http://localhost:8080/api/websocket/broadcast \ -H "Content-Type: text/plain" \ -d "這是一條廣播消息"
7. 進階功能
7.1 心跳檢測
為了保持WebSocket連接的穩(wěn)定性,可以實現(xiàn)心跳機制:
@Scheduled(fixedRate = 10000) // 每10秒發(fā)送一次心跳,需要啟動類或配置類上添加@EnableScheduling public void sendHeartbeat() { String heartbeat = "heartbeat"; sessions.values().forEach(session -> { try { session.sendMessage(new TextMessage(heartbeat)); } catch (IOException e) { log.error("發(fā)送心跳消息失敗", e); } }); }
7.2 消息重試機制
當(dāng)消息發(fā)送失敗時,實現(xiàn)重試機制:
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("消息發(fā)送失敗,嘗試重試 {}/{}", retryCount, maxRetries); try { Thread.sleep(1000); } catch (InterruptedException ie) { Thread.currentThread().interrupt(); break; } } } log.error("消息發(fā)送失敗,達到最大重試次數(shù)"); }
8. 注意事項
連接管理
- 及時清理斷開的連接
- 實現(xiàn)最大連接數(shù)限制
- 考慮使用連接池管理WebSocket連接
安全性
- 實現(xiàn)用戶認證
- 添加消息加密
- 設(shè)置適當(dāng)?shù)目缬虿呗?/li>
性能優(yōu)化
- 使用消息隊列處理大量消息
- 實現(xiàn)消息壓縮
- 控制消息大小
錯誤處理
- 完善異常處理機制
- 實現(xiàn)日志記錄
- 添加監(jiān)控告警
9. 總結(jié)
SpringBoot 3 整合 WebSocket 提供了一種高效的實時通信解決方案。通過本文的配置和示例,你可以快速實現(xiàn):
- WebSocket服務(wù)器端配置
- 客戶端連接管理
- 消息收發(fā)處理
- 廣播功能
- 心跳檢測
- 錯誤處理
這些功能可以作為構(gòu)建實時應(yīng)用的基礎(chǔ),如在線聊天、實時數(shù)據(jù)推送、游戲等場景。根據(jù)具體需求,你可以在此基礎(chǔ)上擴展更多功能。
參考資料
到此這篇關(guān)于SpringBoot3整合WebSocket指南的文章就介紹到這了,更多相關(guān)SpringBoot3整合WebSocket內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
springboot(thymeleaf)中th:field和th:value的區(qū)別及說明
這篇文章主要介紹了springboot(thymeleaf)中th:field和th:value的區(qū)別及說明,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-10-10詳解Java volatile 內(nèi)存屏障底層原理語義
為了保證內(nèi)存可見性,java 編譯器在生成指令序列的適當(dāng)位置會插入內(nèi)存屏障指令來禁止特定類型的處理器重排序。為了實現(xiàn) volatile 內(nèi)存語義,JMM 會分別限制這兩種類型的重排序類型2021-09-09SpringMVC結(jié)合ajaxfileupload實現(xiàn)文件無刷新上傳代碼
本篇文章主要介紹了SpringMVC結(jié)合ajaxfileupload實現(xiàn)文件無刷新上傳,具有一定的參考價值,感興趣的小伙伴們可以參考一下。2017-04-04PowerJob的OmsLogHandler工作流程源碼解析
這篇文章主要為大家介紹了PowerJob的OmsLogHandler工作流程源碼解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-12-12