springboot整合WebSockets廣播訊息(推薦)
一 WebScoketS 簡介
RFC 6455 即 webSockets 協議提供了一種標準化的方式去建立全雙工,雙方面交流的通道在客戶端和服務端甚至單一的TCP連線中進行通訊; webSockets 協議其跟HTTP的tcp協議不同,但是其設計目的是通過HTTP協議進行工作,可以使用40或者443埠和重新使用現有的防火牆規則;
GET /spring-websocket-portfolio/portfolio HTTP/1.1 Host: localhost:8080 Upgrade: websocket Connection: Upgrade Sec-WebSocket-Key: Uc9l9TMkWGbHFD2qnFHltg== Sec-WebSocket-Protocol: v10.stomp,v11.stomp Sec-WebSocket-Version: 13 Origin: http://localhost:8080
webSockets 的互動是以HTTP協議開始的,使用Upgrade header 轉向使用Upgrade連線;如果非200狀態成功響應就類似於下面的資訊;如果WebSocket server 是執行在nginx是需要配置WebSocket upgrade requests ;如果是執行在雲上,需要查閱相關的雲是否支援WebSocket ;
HTTP/1.1 101 Switching Protocols Upgrade: websocket Connection: Upgrade Sec-WebSocket-Accept: 1qVdfYHU9hPOl4JYYNXF623Gzn0= Sec-WebSocket-Protocol: v10.stomp
二 HTTP 和 WebSocket 對比
在HTTP和REST中一個應用需要很多的URLs;應用和客戶端是通過 請求和響應的風格使用這些URLs進行互動;服務端會路由這些請求給基於HTTP 的URL或者方法或者頭進行處理;
WebSockets 通常在初始化的時候就只有一個連結,所有應用的訊息都是通過相同的TCP連線進行流動;這指向一個完全不同的非同步、事件驅動的訊息傳遞體系結構。
WebSocket 是一種低端的協議,不像HTTP,其不規定訊息中內容中任何的語義資訊;這意味著其沒有任何方式去路由或者處理這些資訊,除非客戶端和服務端在語義上達成一致;
WebSocket 客戶端和服務端其交流是通過使用更加高階的訊息協議(比如STOMP)和基於HTTP握手請求的Sec-WebSocket-Protocol header ;
三 注意事項
WebSockets可以使web頁面具有動態性和互動性。然而,在許多情況下,Ajax和HTTP流或 long polling(輪詢)可以提供一個簡單有效的解決方案。HTTP流和polling適用於訊息不頻繁的互動,WebSockets適用於訊息較頻繁的互動;在 因特網上由於沒有Upgrade header 或者 關閉了空閒的長連結,受限於在你有限的代理可能會將WebSockets的互動排除;
四 websocket配置和依賴
4.1 依賴
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.1.RELEASE</version> <relativePath/> </parent> <dependencies> <!-- websocket依賴--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> </dependency> <!-- 模板引擎--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> </dependencies>
4.2 配置
/** * @Author lsc * @Description <p>websocket配置類 </p> * @Date 2019/11/12 22:27 */ //使用STOMP協議來傳輸基於訊息代理的訊息,控制器支援在@Controller類中使用@MessageMapping @EnableWebSocketMessageBroker @Configurable @EnableWebSocket @Component public class WebConfig implements WebSocketMessageBrokerConfigurer { @Override public void registerStompEndpoints(StompEndpointRegistry registry) { // 註冊 Stomp的端點(Endpoint),並且對映指定的url registry.addEndpoint("/websocket") .setAllowedOrigins("*") // 新增允許跨域訪問 .withSockJS();// 指定SockJS協議 } @Override public void configureMessageBroker(MessageBrokerRegistry registry) { // 啟動廣播模式代理,只有符合的的路徑才傳送訊息 registry.enableSimpleBroker("/topic"); } }
五 實體類
5.1 接受訊息實體
/** * @Author lsc * @Description <p> 接受客戶端訊息</p> * @Date 2019/11/12 22:42 */ public class AcceptMessages { private String name; public String getName() { return name; } }
5.2 傳送訊息實體
/** * @Author lsc * @Description <p>傳送訊息給客戶端 </p> * @Date 2019/11/12 22:42 */ public class SendMessages { private String responseMessage; public String getResponseMessage() { return responseMessage; } public void setResponseMessage(String responseMessage) { this.responseMessage = responseMessage; } }
六控制器
/** * @Author lsc * @Description <p>websockets 之 廣播式</p> * @Date 2019/11/12 22:49 */ @Controller public class WebSocketsController { @MessageMapping("/welcome")//類似@RequestMapping,進行客戶端請求地址對映 @SendTo("/topic/getResponse")//訂閱了@SendTo中的路徑進行傳送訊息 public SendMessages broadcast(AcceptMessages acceptMessages){ System.out.println(acceptMessages.getName()); SendMessages sendMessages = new SendMessages(); sendMessages.setResponseMessage("知識追尋者:"+acceptMessages.getName()); return sendMessages; } }
七 前端頁面
在 resource目錄下新建templates目錄存放WebSockets.html;在resource目錄下新建static目錄,繼續在其子目錄下新建js目錄存放sockjs.min.js,stomp.min.js,jquery-3.3.1.min.js;
<!DOCTYPE html> <html lang="en" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"/> <title>springboot廣播式WebSocket</title> </head> <body onload="disconnect()"> <noscript><h2 style="color: #ffff0000;">Sorry,not support the 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="@{js/sockjs.min.js}"></script> <script th:src="@{js/stomp.min.js}"></script> <script th:src="@{js/jquery-3.3.1.min.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() { // 轉向 endpoint 名為websocket var socket = new SockJS('/websocket'); // 使用ssocket的協議 stompClient = Stomp.over(socket); // 連線 stompClient.connect({},function (frame) { setConnected(true); console.log('Connected:' + frame); // @Sendto 中定義路徑 向目標訂閱訊息 stompClient.subscribe('/topic/getResponse',function (response) { showResponse(JSON.parse(response.body).responseMessage); }) }); } function disconnect() { if (stompClient != null) { stompClient.disconnect(); } setConnected(false); console.log('Disconnected'); } function sendName() { var name = $('#name').val(); // 控制器@MessageMapping中定義向目標傳送訊息 stompClient.send("/welcome",{},JSON.stringify({'name': name})); } function showResponse(message) { $("#response").html(message); } </script> </body> </html>
八 檢視轉發
當客戶端請求地址是localhost:8080/ws,經過springmvc檢視轉發器至WebSockets.html;
/** * @Author lsc * @Description <p> spingmvc檢視對映轉發</p> * @Date 2019/11/12 23:35 */ @Configurable @Component public class WebMvcConfig implements WebMvcConfigurer { @Override public void addViewControllers(ViewControllerRegistry registry) { // 配置檢視轉發 registry.addViewController("/ws").setViewName("/WebSockets"); } }
九 效果圖
即一個瀏覽器傳送訊息,其它連線的瀏覽器也能收到訊息,即廣播形式;
十 參考文獻
spring-web
原始碼
總結
以上所述是小編給大家介紹的springboot整合WebSockets廣播訊息,希望對大家有所幫助!