Spring boot+VUE+websocket 實現消息推送


  • 背景:

        最近涉及消息通知功能,在管理員創建發送消息時,登陸用戶可以實時接收到新增消息的提醒,避免頻繁刷新,通過websocket取代輪詢setInterval。

  • Spring boot部分:
  • POM.xml
		<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> </dependency>
  • 新建配置類:
package io.xcc.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.socket.server.standard.ServerEndpointExporter; @Configuration public class WebSocketConfig { /** * 注入ServerEndpointExporter, * 這個bean會自動注冊使用了@ServerEndpoint注解聲明的Websocket endpoint */ @Bean public ServerEndpointExporter serverEndpointExporter() { return new ServerEndpointExporter(); } }
  • 新建實現類:
package io.xcc.common.socket; import java.util.HashMap; import java.util.Map; import java.util.concurrent.CopyOnWriteArraySet; import javax.websocket.OnClose; import javax.websocket.OnMessage; import javax.websocket.OnOpen; import javax.websocket.Session; import javax.websocket.server.PathParam; import javax.websocket.server.ServerEndpoint; import org.springframework.stereotype.Component; @Component @ServerEndpoint("/websocket/{userName}") //此注解相當於設置訪問URL public class WebSocket { private Session session; private static CopyOnWriteArraySet<WebSocket> webSockets =new CopyOnWriteArraySet<>(); private static Map<String,Session> sessionPool = new HashMap<String,Session>(); @OnOpen public void onOpen(Session session, @PathParam(value="userName")String userName) { this.session = session; webSockets.add(this); sessionPool.put(userName, session); System.out.println(userName+"【websocket消息】有新的連接,總數為:"+webSockets.size()); } @OnClose public void onClose() { webSockets.remove(this); System.out.println("【websocket消息】連接斷開,總數為:"+webSockets.size()); } @OnMessage public void onMessage(String message) { System.out.println("【websocket消息】收到客戶端消息:"+message); } // 此為廣播消息 public void sendAllMessage(String message) { for(WebSocket webSocket : webSockets) { System.out.println("【websocket消息】廣播消息:"+message); try { webSocket.session.getAsyncRemote().sendText(message); } catch (Exception e) { e.printStackTrace(); } } } // 此為單點消息 public void sendOneMessage(String userName, String message) { System.out.println("【websocket消息】單點消息:"+message); Session session = sessionPool.get(userName); if (session != null) { try { session.getAsyncRemote().sendText(message); } catch (Exception e) { e.printStackTrace(); } } } }
  • 新增調用類:
    @GetMapping("/sendAllWebSocket") public String test() { String text="你們好!這是websocket群體發送!"; webSocket.sendAllMessage(text); return text; } @GetMapping("/sendOneWebSocket/{userName}") public String sendOneWebSocket(@PathVariable("userName") String userName) { String text=userName+" 你好! 這是websocket單人發送!"; webSocket.sendOneMessage(userName,text); return text; }
  • VUE部分:
  mounted () { // WebSocket if ('WebSocket' in window) { this.websocket = new WebSocket('ws://localhost:8801/myproject/websocket/' + this.userName) this.initWebSocket() } else { alert('當前瀏覽器 Not support websocket') } }, beforeDestroy () { this.onbeforeunload() }, methods: { initWebSocket () { // 連接錯誤 this.websocket.onerror = this.setErrorMessage // 連接成功 this.websocket.onopen = this.setOnopenMessage // 收到消息的回調 this.websocket.onmessage = this.setOnmessageMessage // 連接關閉的回調 this.websocket.onclose = this.setOncloseMessage // 監聽窗口關閉事件,當窗口關閉時,主動去關閉websocket連接,防止連接還沒斷開就關閉窗口,server端會拋異常。 window.onbeforeunload = this.onbeforeunload }, setErrorMessage () { console.log('WebSocket連接發生錯誤 狀態碼:' + this.websocket.readyState) }, setOnopenMessage () { console.log('WebSocket連接成功 狀態碼:' + this.websocket.readyState) }, setOnmessageMessage (event) { // 根據服務器推送的消息做自己的業務處理 console.log('服務端返回:' + event.data) }, setOncloseMessage () { console.log('WebSocket連接關閉 狀態碼:' + this.websocket.readyState) }, onbeforeunload () { this.closeWebSocket() }, closeWebSocket () { this.websocket.close() } }
  • 測試效果:

 http://localhost:8801/myproject/app/sendOneWebSocket/admin

http://localhost:8801/myproject/app/sendOneWebSocket/czm

http://localhost:8801/myproject/app/sendAllWebSocket

用兩個瀏覽器分別登陸兩個賬號,控制台結果如下圖:

                          【圖1】

                        【圖2】

  • 參考主要來源:

            https://segmentfault.com/a/1190000017268973

  • 其他注意事項:
  1. 不要試圖通過單元測試測試,因為session不同獲取不到;
  2. 設置完前台沒有顯示鏈接成功,請注意修改自己的過濾器;


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM