javascript
使用 Spring Boot websocket 写简单网页聊天室
Spring Boot 為 websocket 提供了一些默認配置,簡化了 websocket 使用,這里我們將使用 Spring Boot websocket,并加入 stomp 和 sockjs 的支持,快速編寫一個簡單的網頁聊天室,實現廣播消息推送以及點對點的私人消息推送。
篇幅限制下邊只給出關鍵的代碼,需要 HTML 頁面代碼或項目完整源代碼的可到這里查看(使用 IDEA 導入后可直接運行)。
基本頁面:
將服務器關閉,客戶端自動重連:
超過重連次數后,不再重連:
項目的編寫分為服務器端和客戶端,因此下邊也就分為這兩個方面進行講述
服務端
由于 spring boot 的默認配置,大大簡化了開發,服務器端需要編寫的只有兩個地方:配置類和控制器。
當然首先需要引入依賴(這里使用 gradle 作為包管理工具)
compile('org.springframework.boot:spring-boot-starter-web') compile('org.springframework.boot:spring-boot-starter-websocket')編寫配置類
然后是 websocket 的配置類 WebSocketConfig,配置項的解釋見注釋
@Configuration @EnableWebSocketMessageBroker public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {@Overridepublic void configureMessageBroker(MessageBrokerRegistry registry) {registry.enableSimpleBroker("/topic", "/user");// “/topic“ 用于給客戶端訂閱廣播信息,”/user“用于給客戶端訂閱點對點消息//registry.setApplicationDestinationPrefixes("/app");// 客戶端向服務器發送消息時 URL 為:【/app + controller中 @MessageMapping 的地址】,此處暫時不使用該配置//registry.setUserDestinationPrefix("/user/");// 客戶端向指定用戶發送(一對一)信息時 URL 前綴是“/user/”,即使不配置默認也是“/user/“}@Overridepublic void registerStompEndpoints(StompEndpointRegistry registry) {registry.addEndpoint("/endpoint").withSockJS();//注冊客戶端websocket連接的端口} }編寫 controller
@Controller public class WebsocketController {/*** 廣播推送* @param text* @param sessionId* @return* @throws Exception*/@MessageMapping(value = "/chat")@SendTo("/topic/getResponse")public String talk(@Payload String text, @Header("simpSessionId") String sessionId) throws Exception {return "【" + sessionId + "】說:【" + text + "】";}/*** 點對點推送* @param text* @param sessionId* @return* @throws Exception*/@MessageMapping(value = "/speak")@SendToUser(value = "/personal")public String speak(@Payload String text, @Header("simpSessionId") String sessionId) throws Exception {return text;}/*** 異常信息推送* @param exception* @return*/@MessageExceptionHandler@SendToUser(value = "/errors")public String handleException(Throwable exception) {return exception.getMessage();} }這里需要說一下其中用到的幾個注解:
- 方法注解
- @MessageMapping(value = “/URL”) 匹配客戶端 send 消息時的URL;
- @sendTo 和 @sendToUser 分別用于給客戶端訂閱廣播消息和點對點消息;
- 參數注解
- @Payload:使用客戶端 STOMP 幀的 body 賦值;
- @Header(“xxx”):使用客戶端 STOMP 幀的 headers 中的 xxx 賦值;
在查閱資料的時候,看到也可以使用 SimpMessagingTemplate 進行消息的代理轉發,可以這么理解:
@MessageMapping("/chat") public void chat(String value){this.simpMessagingTemplate.convertAndSend("/topic/getResponse", value); }等同于
@MessageMapping("/chat") @SendTo("/topic/getResponse") public String chat(String value) {return value; }客戶端
客戶端的代碼主要是使用 JavaScript 進行 websocket 的一系列操作,由于使用 STOMP 協議,因此需要使用 STOMP API, 關于 STOMP API 的使用,可以參考這里的 總結。
基本操作如下
var socket = new SockJS('/endpoint'); stompClient = Stomp.over(socket); stompClient.connect({}, function connectCallback (frame) {...}, function errorCallBack (error) {...} );一對一消息推送
// 獲取 socket 連接的sessionId,即從 socket._transport.url 中使用正則截取 var sessionId = /\/([^\/]+)\/websocket/.exec(socket._transport.url)[1]; console.log("connected, session id: " + sessionId); ...... // 訂閱私人消息 var subscription_personal = stompClient.subscribe('/user/' + sessionId + '/personal', function callBack (response) {if (response.body) {printToScreen("【私人消息】" + response.body);} else {printToScreen("收到一個空消息");} } ...... // 發送消息 stompClient.send("/speak", headers, JSON.stringify(body));廣播消息推送
...... // 訂閱廣播消息 var subscription_broadcast = stompClient.subscribe('/topic/getResponse', function callBack (response) {if (response.body) {printToScreen("【廣播】" + response.body);} else {printToScreen("收到一個空消息");} }); ...... // 發送廣播消息 stompClient.send("/chat", headers, JSON.stringify(body));異常消息推送
// 獲取 websocket 連接的 sessionId var sessionId = /\/([^\/]+)\/websocket/.exec(socket._transport.url)[1]; // 訂閱異常消息 var subscription_errors = stompClient.subscribe('/user/' + sessionId + '/errors', function callBack (response) {if (response.body) {printToScreen("【異常消息】" + response.body);} else {printToScreen("收到一個空消息");} });自動重連機制
使用JavaScript設置自動重連機制,與服務器斷開連接后自動重來,重連失敗超過10后不再重連
function errorCallBack (error) {document.getElementById("state-info").innerHTML = "連接斷開";console.log('連接斷開【' + error + '】');if (curTryNum <= maxTryNum) {document.getElementById("state-info").innerHTML = "連接關閉,10秒后重新連接……";console.log("連接關閉,10秒后重新連接……");// 10秒后重新連接,實際效果:每10秒重連一次,直到連接成功setTimeout(function () {connect();}, 10000);} else {document.getElementById("state-info").innerHTML = "連接關閉,且已超過最大重連次數,不再重連";console.log("連接關閉,且已超過最大重連次數,不再重連");} }總結
以上是生活随笔為你收集整理的使用 Spring Boot websocket 写简单网页聊天室的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【手机跳板 多款软件测试】图文演示!
- 下一篇: extjs获取元素name属性值_【Ex