如題,今天介紹的是 SpringBoot 整合 WebSocket 實現廣播消息。javascript
WebSocket 爲瀏覽器和服務器提供了雙工異步通訊的功能,即瀏覽器能夠向服務器發送信息,反之也成立。html
WebSocket 是經過一個 socket 來實現雙工異步通訊能力的,但直接使用 WebSocket ( 或者 SockJS:WebSocket 協議的模擬,增長了當前瀏覽器不支持使用 WebSocket 的兼容支持) 協議開發程序顯得十分繁瑣,因此使用它的子協議 STOMP。前端
它是高級的流文本定向消息協議,是一種爲 MOM (Message Oriented Middleware,面向消息的中間件) 設計的簡單文本協議。java
它提供了一個可互操做的鏈接格式,容許 STOMP 客戶端與任意 STOMP 消息代理 (Broker) 進行交互,相似於 OpenWire (一種二進制協議)。jquery
因爲其設計簡單,很容易開發客戶端,所以在多種語言和多種平臺上獲得普遍應用。其中最流行的 STOMP 消息代理是 Apache ActiveMQ。git
STOMP 協議使用一個基於 (frame) 的格式來定義消息,與 Http 的 request 和 response 相似 。github
接下來,實現一個廣播消息的 demo。即服務端有消息時,將消息發送給全部鏈接了當前 endpoint 的瀏覽器。web
<dependencies> <!-- thymeleaf 模板引擎 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> <!-- web 啓動類 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- WebSocket 依賴 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> </dependency> <!-- test 單元測試 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies>
代碼註釋很詳細,很少說。算法
實現 WebSocketMessageBrokerConfigurer 接口,註冊一個 STOMP 節點,配置一個廣播消息代理spring
@Configuration // @EnableWebSocketMessageBroker註解用於開啓使用STOMP協議來傳輸基於代理(MessageBroker)的消息,這時候控制器(controller) // 開始支持@MessageMapping,就像是使用@requestMapping同樣。 @EnableWebSocketMessageBroker public class WebSocketConfig implements WebSocketMessageBrokerConfigurer { @Override public void registerStompEndpoints(StompEndpointRegistry registry) { //註冊一個 Stomp 的節點(endpoint),並指定使用 SockJS 協議。 registry.addEndpoint("/endpointNasus").withSockJS(); } @Override public void configureMessageBroker(MessageBrokerRegistry registry) { // 廣播式配置名爲 /nasus 消息代理 , 這個消息代理必須和 controller 中的 @SendTo 配置的地址前綴同樣或者全匹配 registry.enableSimpleBroker("/nasus"); } }
客戶端發送給服務器:
public class Client2ServerMessage { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } }
服務器發送給客戶端:
public class Server2ClientMessage { private String responseMessage; public Server2ClientMessage(String responseMessage) { this.responseMessage = responseMessage; } public String getResponseMessage() { return responseMessage; } public void setResponseMessage(String responseMessage) { this.responseMessage = responseMessage; } }
@RestController public class WebSocketController { @MessageMapping("/hello") // @MessageMapping 和 @RequestMapping 功能相似,瀏覽器向服務器發起消息,映射到該地址。 @SendTo("/nasus/getResponse") // 若是服務器接受到了消息,就會對訂閱了 @SendTo 括號中的地址的瀏覽器發送消息。 public Server2ClientMessage say(Client2ServerMessage message) throws Exception { Thread.sleep(3000); return new Server2ClientMessage("Hello," + message.getName() + "!"); } }
將 stomp.min.js (STOMP 客戶端腳本) 和 sockJS.min.js (sockJS 客戶端腳本) 以及 Jquery 放在 resource 文件夾的 static 目錄下。
<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8" /> <title>Spring Boot+WebSocket+廣播式</title> </head> <body onload="disconnect()"> <noscript><h2 style="color: #ff0000">貌似你的瀏覽器不支持websocket</h2></noscript> <div> <div> <button id="connect" onclick="connect();">鏈接</button> <button id="disconnect" disabled="disabled" onclick="disconnect();">斷開鏈接</button> </div> <div id="conversationDiv"> <label>輸入你的名字</label><input type="text" id="name" /> <button id="sendName" onclick="sendName();">發送</button> <p id="response"></p> </div> </div> <script th:src="@{sockjs.min.js}"></script> <script th:src="@{stomp.min.js}"></script> <script th:src="@{jquery.js}"></script> <script type="text/javascript"> var stompClient = null; function setConnected(connected) { document.getElementById('connect').disabled = connected; document.getElementById('disconnect').disabled = !connected; document.getElementById('conversationDiv').style.visibility = connected ? 'visible' : 'hidden'; $('#response').html(); } function connect() { // 鏈接 SockJs 的 endpoint 名稱爲 "/endpointNasus" var socket = new SockJS('/endpointNasus'); // 使用 STOMP 子協議的 WebSocket 客戶端 stompClient = Stomp.over(socket); stompClient.connect({}, function(frame) { setConnected(true); console.log('Connected: ' + frame); // 經過 stompClient.subscribe 訂閱 /nasus/getResponse 目標發送的信息,對應控制器的 SendTo 定義 stompClient.subscribe('/nasus/getResponse', function(respnose){ // 展現返回的信息,只要訂閱了 /nasus/getResponse 目標,均可以接收到服務端返回的信息 showResponse(JSON.parse(respnose.body).responseMessage); }); }); } function disconnect() { // 斷開鏈接 if (stompClient != null) { stompClient.disconnect(); } setConnected(false); console.log("Disconnected"); } function sendName() { // 向服務端發送消息 var name = $('#name').val(); // 經過 stompClient.send 向 /hello (服務端)發送信息,對應控制器 @MessageMapping 中的定義 stompClient.send("/hello", {}, JSON.stringify({ 'name': name })); } function showResponse(message) { // 接收返回的消息 var response = $("#response"); response.html(message); } </script> </body> </html>
注意,這裏使用的是 @Controller 註解,用於匹配 html 前綴,加載頁面。
@Controller public class ViewController { @GetMapping("/nasus") public String getView(){ return "nasus"; } }
打開三個窗口訪問 http://localhost:8080/nasus ,初始頁面長這樣:
三個頁面所有點鏈接,點擊鏈接訂閱 endpoint ,以下圖:
在第一個頁面,輸入名字,點發送 ,以下圖:
在第一個頁面發送消息,等待 3 秒,結果是 3 個頁面都接受到了服務端返回的信息,廣播成功。
源碼下載:
https://github.com/turoDog/De...
若是以爲對你有幫助,請給個 Star 再走唄,很是感謝。
若是本文對你哪怕有一丁點幫助,請幫忙點好看。你的好看是我堅持寫做的動力。
另外,關注以後在發送 1024 可領取免費學習資料。
資料詳情請看這篇舊文:Python、C++、Java、Linux、Go、前端、算法資料分享