close
關注我,回復關鍵字「spring」,
免費領取Spring學習資料。

寫在前面

此異常非彼異常,標題所說的異常是業務上的異常。

最近做了一個需求,消防的設備巡檢,如果巡檢發現異常,通過手機端提交,後台的實時監控頁面實時獲取到該設備的信息及位置,然後安排員工去處理。

因為需要服務端主動向客戶端發送消息,所以很容易的就想到了用WebSocket來實現這一功能。

WebSocket就不做介紹了,上鏈接:https://developer.mozilla.org/zh-CN/docs/Web/API/WebSocket

前端略微複雜,需要在一張位置分布圖上進行鼠標描點定位各個設備和根據不同屏幕大小渲染,本文不做介紹,只是簡單地用頁面樣式進行效果呈現。

綠色代表正常,紅色代表異常

預期效果,未接收到請求前----->id為3的提交了異常,id為3的王五變成了紅色

實現前端:

直接貼代碼

1<!DOCTYPEhtml>2<html>3<head>4<metacharset="utf-8"/>5<title>實時監控</title>6</head>7<style>8.item{9display:flex;10border-bottom:1pxsolid#000000;11justify-content:space-between;12width:30%;13line-height:50px;14height:50px;15}1617.itemspan:nth-child(2){18margin-right:10px;19margin-top:15px;20width:20px;21height:20px;22border-radius:50%;23background:#55ff00;24}25.nowI{26background:#ff0000!important;27}28</style>29<body>30<divid="app">31<divv-for="iteminlist"class="item">32<span>{{item.id}}.{{item.name}}</span>33<span:class='item.state==-1?"nowI":""'></span>34</div>35</div>36</body>37<scriptsrc="./js/vue.min.js"></script>38<scripttype="text/javascript">39varvm=newVue({40el:"#app",41data:{42list:[{43id:1,44name:'張三',45state:146},47{48id:2,49name:'李四',50state:151},52{53id:3,54name:'王五',55state:156},57{58id:4,59name:'韓梅梅',60state:161},62{63id:5,64name:'李磊',65state:166},67]68}69})7071varwebSocket=null;72if('WebSocket'inwindow){73//創建WebSocket對象74webSocket=newWebSocket("ws://localhost:18801/webSocket/"+getUUID());7576//連接成功77webSocket.onopen=function(){78console.log("已連接");79webSocket.send("消息發送測試")80}81//接收到消息82webSocket.onmessage=function(msg){83//處理消息84varserverMsg=msg.data;85vart_id=parseInt(serverMsg)//服務端發過來的消息,ID,string需轉化為int類型才能比較86for(vari=0;i<vm.list.length;i++){87varitem=vm.list[i];88if(item.id==t_id){89item.state=-1;90vm.list.splice(i,1,item)91break;92}93}94};9596//關閉事件97webSocket.onclose=function(){98console.log("websocket已關閉");99};100//發生了錯誤事件101webSocket.onerror=function(){102console.log("websocket發生了錯誤");103}104}else{105alert("很遺憾,您的瀏覽器不支持WebSocket!")106}107108functiongetUUID(){//獲取唯一的UUID109return'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g,function(c){110111varr=Math.random()*16|0,112v=c=='x'?r:(r&0x3|0x8);113returnv.toString(16);114});115}116</script>117</html>後端:

項目結構是這樣子的,後面的代碼關鍵注釋都有,就不重複描述了

1、新建SpringBoot工程,選擇web和WebSocket依賴

2、配置application.yml

#端口server:port:18801#密碼,因為接口不需要權限,所以加了個密碼做校驗mySocket:myPwd:jae_123

3、WebSocketConfig配置類

1@Configuration2publicclassWebSocketConfig{34/**5*注入一個ServerEndpointExporter,該Bean會自動註冊使用@ServerEndpoint註解申明的websocketendpoint6*/7@Bean8publicServerEndpointExporterserverEndpointExporter(){9returnnewServerEndpointExporter();10}11}

4、WebSocketServer類,用來進行服務端和客戶端之間的交互

1/**2*@authorjae3*@ServerEndpoint("/webSocket/{uid}")前端通過此URI與後端建立鏈接4*/56@ServerEndpoint("/webSocket/{uid}")7@Component8publicclassWebSocketServer{910privatestaticLoggerlog=LoggerFactory.getLogger(WebSocketServer.class);1112//靜態變量,用來記錄當前在線連接數。應該把它設計成線程安全的。13privatestaticfinalAtomicIntegeronlineNum=newAtomicInteger(0);1415//concurrent包的線程安全Set,用來存放每個客戶端對應的WebSocketServer對象。16privatestaticCopyOnWriteArraySet<Session>sessionPools=newCopyOnWriteArraySet<Session>();1718/**19*有客戶端連接成功20*/21@OnOpen22publicvoidonOpen(Sessionsession,@PathParam(value="uid")Stringuid){23sessionPools.add(session);24onlineNum.incrementAndGet();25log.info(uid+"加入webSocket!當前人數為"+onlineNum);26}2728/**29*連接關閉調用的方法30*/31@OnClose32publicvoidonClose(Sessionsession){33sessionPools.remove(session);34intcnt=onlineNum.decrementAndGet();35log.info("有連接關閉,當前連接數為:{}",cnt);36}3738/**39*發送消息40*/41publicvoidsendMessage(Sessionsession,Stringmessage)throwsIOException{42if(session!=null){43synchronized(session){44session.getBasicRemote().sendText(message);45}46}47}4849/**50*群發消息51*/52publicvoidbroadCastInfo(Stringmessage)throwsIOException{53for(Sessionsession:sessionPools){54if(session.isOpen()){55sendMessage(session,message);56}57}58}5960/**61*發生錯誤62*/63@OnError64publicvoidonError(Sessionsession,Throwablethrowable){65log.error("發生錯誤");66throwable.printStackTrace();67}6869}

5、WebSocketController類,用於進行接口測試

1@RestController2@RequestMapping("/open/socket")3publicclassWebSocketController{45@Value("${mySocket.myPwd}")6publicStringmyPwd;78@Autowired9privateWebSocketServerwebSocketServer;1011/**12*手機客戶端請求接口13*@paramid發生異常的設備ID14*@parampwd密碼(實際開發記得加密)15*@throwsIOException16*/17@PostMapping(value="/onReceive")18publicvoidonReceive(Stringid,Stringpwd)throwsIOException{19if(pwd.equals(myPwd)){//密碼校驗一致(這裡舉例,實際開發還要有個密碼加密的校驗的),則進行群發20webSocketServer.broadCastInfo(id);21}22}2324}測試

1、打開前端頁面,進行WebSocket連接

控制台輸出,連接成功

2、因為是模擬數據,所以全部顯示正常,沒有異常提交時的頁面呈現

3、接下來,我們用接口測試工具Postman提交一個異常

注意id為3的這個數據的狀態變化

我們可以看到,id為3的王五狀態已經變成異常的了,實時通訊成功。

參考:https://developer.mozilla.org/zh-CN/docs/Web/API/WebSocket

最後

工作中有這方面關於實時監控的需求,可以參考一下哦。

不足之處歡迎指出,覺得有用的話就點個推薦吧!



END


Spring Boot 使用 Disruptor 做內部高性能消息隊列
為什麼不建議使用ON DUPLICATE KEY UPDATE?
程序員缺乏經驗的 7 種表現
最新 955 不加班的公司名單
Spring Boot 項目鑒權的 4 種方式

關注後端面試那些事,回復【2022面經】

獲取最新大廠Java面經


最後重要提示:高質量的技術交流群,限時免費開放,今年抱團最重要。想進群的,關注SpringForAll社區,回復關鍵詞:加群,拉你進群。




點擊「閱讀原文」領取2022大廠面經
↓↓↓
arrow
arrow
    全站熱搜
    創作者介紹
    創作者 鑽石舞台 的頭像
    鑽石舞台

    鑽石舞台

    鑽石舞台 發表在 痞客邦 留言(0) 人氣()