原文:https://www.cnblogs.com/xiaozhengtongxue/p/13448778.html
- websocket: 在瀏覽器和服務器之間建立TCP連接,實現全雙工通信
springboot使用websocket有兩種方式,一種是實現簡單的websocket,另外一種是實現STOMP協議。本篇講述如何使用springboot實現簡單的websocket。
直接在pom.xml
中導入依賴。
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> </dependency>
首先注入一個ServerEndpointExporterBean,該Bean會自動注冊使用@ServerEndpoint注解申請的websocket endpoint,代碼如下:
@Component public class WebSocketConfig { @Bean public ServerEndpointExporter serverEndpointExporter(){ return new ServerEndpointExporter(); } }
新建websocket 服務端,在其中處理websocket 邏輯
@Component //注冊到容器中 //@ServerEndpoint("/webSocket") //接收websocket請求路徑
@ServerEndpoint("/websocket/{id}")
@Slf4j public class WebSocket { //當前連接(每個websocket連入都會創建一個WebSocket實例) private Session session; //定義一個websocket容器存儲session,即存放所有在線的socket,連接可以改為map private static CopyOnWriteArraySet<WebSocket> webSocketSet = new CopyOnWriteArraySet<>(); //處理連接建立,獲取用戶id @OnOpen public void opOpen(@PathParam(value = "id") String id,Session session){ this.session = session; log.info("【有新的客戶端連接了】:{}",session.getId()); webSocketSet.add(this); //將新用戶加入在線組 log.info("【websocket消息】有新的連接,總數:{}",webSocketSet.size()); } //處理連接關閉 @OnClose public void Onclose(){ webSocketSet.remove(this); log.info("【websocket消息】連接斷開,總數:{}",webSocketSet.size()); } //接受消息 @OnMessage public void onMessage(String message){ log.info("【websocket消息】收到客戶端發來的消息:{}",message); } // 群發消息 public void sendMessage(String message) { for (WebSocket webSocket : webSocketSet) { log.info("【websocket消息】廣播群發消息,message={}",message); try { webSocket.session.getBasicRemote().sendText(message); }catch (Exception e){ e.printStackTrace(); } } } }
客戶可以使用freeMarker模板工具實現。
前端實現,建議:https://blog.csdn.net/LiLi_code/article/details/86583347
由於部分瀏覽器可能不支持,可以先測試,代碼如下:
<script> var websocket = null; if('WebSocket' in window){ websocket = new WebSocket('ws://localhost:8080/webSocket'); }else{ alert('當前瀏覽器不支持websocket消息通知'); } //連接成功建立的回調方法 websocket.onopen = function (event) { console.log("ws建立連接成功"); } //連接關閉的回調方法 websocket.onclose = function (event) { console.log("ws連接關閉"); } //接收到消息的回調方法 websocket.onmessage = function (event) { /*setMessageInnerHTML(event.data);*/ // alert("ws接收返回消息:"+event.data); console.log("服務器返回消息: " + event.data); //彈窗提醒(要用到JQuary,所以要先引入JQuary) 播放音樂 $('#mymodal').modal('show') } //連接發生錯誤的回調方法 websocket.onerror = function(event){ alert('websocket通信發生錯誤!') } //監聽窗口關閉事件,當窗口關閉時,主動去關閉websocket連接,防止連接還沒斷開就關閉窗口,server端會拋異常。 window.onbeforeunload = function() { websocket.close(); } </script>
測試:(項目實現客戶創建訂單之后,前台發出提醒)
@Autowired private WebSocket webSocket; @Override @Transactional public OrderDTO create(OrderDTO orderDTO) {//創建訂單 。。。。(具體代碼省略) //創建新訂單 發送websocket消息 webSocket.sendMessage(orderDTO.getOrderId()); return orderDTO; }
添加新訂單:
前端實現,建議:https://blog.csdn.net/LiLi_code/article/details/86583347
index.html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>聊天室</title> </head> <body> <div id="main"> <p> <input type="text" id="username" placeholder="請輸入用戶名"/> <button type="button" id="addBtn">加入</button> </p> <p> <input type="text" id="message" placeholder="請輸入聊天信息"/> <button type="button" id="sendBtn" disabled>發送</button> </p> <ul id="msg"></ul> </div> </body> <script> window.onload = function () { //獲取button對象 let addBtn = document.getElementById("addBtn") let sendBtn = document.getElementById("sendBtn") let username = document.getElementById("username") var message = document.getElementById("message") //定義全局 let ws = null; addBtn.onclick = function () { join() } //給文本框添加鍵盤點擊事件 username.onkeyup = function (e) { //如果輸入的是回車,進聊天室 if (e.keyCode === 13) { join() username.disabled = true } } sendBtn.onclick = function () { sendMessage() } message.onkeyup = function(e){ if(e.keyCode === 13) sendMessage() } function join() { addBtn.disabled = true sendBtn.disabled = false // 創建WebSocket對象,WebSocket使用的是ws協議 ws = new WebSocket('ws://localhost:2555') ws.onopen = function () { let username = document.getElementById("username").value // 項服務器端發送消息 ws.send( // 往后台發送json字符串 JSON.stringify({ username: username, type: 'login' //添加的對象 }) ) } // onmessage與ws已經綁定,接受消息回來的時候還是會回到這里來 // 服務器發送消息后會觸發 ws.onmessage = function (e) { console.log(e.data) //字符串對象轉json對象 let data = JSON.parse(e.data) let show switch (data.type) { case 'login': //新用戶 show = `${data.username}加入了房間` break; case 'msg': // 有新的聊天信息 show = `${data.username} ${data.time} <br> ${data.message}` break case 'leave': //有人離開聊天室 show = `${data.username}離開了房間 ${data.time}` break; } let li = document.createElement("li") li.innerHTML = show document.getElementById("msg").append(li) } } function sendMessage() { let username = document.getElementById("username").value let msg = document.getElementById("message").value //發送聊天消息給服務器 ws.send(JSON.stringify({ username: username, message: msg, type: 'msg' })) document.getElementById("message").value = '' } } </script> </html>
app.js //后台服務器代碼 //引入websocket模塊 let ws = require('nodejs-websocket') //創建服務對象啟動,監聽端口號是2555 let server = ws.createServer((conn)=>{ console.log('有人連接...') //當客戶端發消息時會觸發text事件 conn.on('text',(str)=>{ let data = JSON.parse(str) console.log(data) //判斷接受消息的類型 switch(data.type){ case 'login': //新用戶加入 conn.nickname = data.username //保存用戶名屬性 broadcast( //發送json字符串告訴客戶端有新用戶加入 JSON.stringify({ username:data.username, time:getTime(), type:data.type }) ) break case 'msg': broadcast( JSON.stringify({ username:data.username, time:getTime(), message:data.message, type:data.type }) ) break } }) //監聽錯誤信息 conn.on('error',(err)=>{ console.log(err) }) //監聽斷開連接 conn.on('close',()=>{ broadcast( JSON.stringify({ username:conn.nickname, time:getTime(), type:'leave' }) ) }) }).listen(2555) //給所有客戶端連接發送消息 function broadcast(str){ //遍歷所有的客戶端連接 server.connections.forEach((conn)=>{ //發送消息 conn.send(str) }) } function getTime(){ var date = new Date(); var hour = date.getHours(); var min = date.getMinutes() var sec = date.getSeconds() return hour + ":" + min + ":" + sec }
不要忘記實現導入websocket框架;
-
安裝包 nodejs-websocket
-
npm install nodejs-websocket