springboot結合websocket聊天室實現(xiàn)私聊+群聊
更新時間:2022年07月28日 08:30:00 作者:符華-
本文主要介紹了springboot結合websocket聊天室實現(xiàn)私聊+群聊,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
?? 先看效果
一人分飾多角(bushi)
?? 后端代碼
?? 先引入websocket依賴
<!-- websocket消息推送 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> </dependency>
???? 添加 WebSocketConfig 配置
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.socket.server.standard.ServerEndpointExporter; @Configuration public class WebSocketConfig { @Bean public ServerEndpointExporter serverEndpointExporter() { return new ServerEndpointExporter(); } }
?????? 實體bean接收客戶端發(fā)過來的信息
@Data public class SocketMsg { /** * 聊天類型 0 群聊 1 單聊 **/ private int type; /** * 發(fā)送者 **/ private String sendOutUser; /** * 接受者 **/ private String receiveUser; /** * 消息 **/ private String msg; }
???????? WebSocketUtil
import cn.hutool.json.JSONUtil; import org.springframework.stereotype.Component; import javax.websocket.*; import javax.websocket.server.PathParam; import javax.websocket.server.ServerEndpoint; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CopyOnWriteArraySet; /** * WebSocket 連接測試 */ @Component @ServerEndpoint("/web-socket/{userName}") public class WebSocketUtil { private String userName; private Session session; /** 固定前綴 */ private static final String USER_NAME_PREFIX = "user_name_"; /** * 用來存放每個客戶端對應的MyWebSocket對象。 **/ private static CopyOnWriteArraySet<WebSocketUtil> webSocketSet = new CopyOnWriteArraySet<>(); /** * 存放Session集合,方便推送消息 (javax.websocket.Session) */ private static ConcurrentHashMap<String, Session> sessionMap = new ConcurrentHashMap<>(); /** * 私聊:向指定客戶端推送消息 */ public synchronized static void privateMessage(SocketMsg socketMsg) { //接收消息的用戶 Session receiveUser = sessionMap.get(USER_NAME_PREFIX + socketMsg.getReceiveUser()); //發(fā)送給接收者 if(receiveUser != null){ //發(fā)送給接收者 System.out.println(socketMsg.getSendOutUser()+" 向 "+socketMsg.getReceiveUser()+" 發(fā)送了一條消息:"+socketMsg.getMsg()); receiveUser.getAsyncRemote().sendText(socketMsg.getSendOutUser()+":"+socketMsg.getMsg()); }else{ //發(fā)送消息的用戶 System.out.println(socketMsg.getSendOutUser()+" 私聊的用戶 "+socketMsg.getReceiveUser()+" 不在線或者輸入的用戶名不對"); Session sendOutUser = sessionMap.get(USER_NAME_PREFIX + socketMsg.getSendOutUser()); //將系統(tǒng)提示推送給發(fā)送者 sendOutUser.getAsyncRemote().sendText("系統(tǒng)消息:對方不在線或者您輸入的用戶名不對"); } } /** * 群聊:公開聊天記錄 * @param userName 發(fā)送者的用戶名稱(當前用戶) * @param message 發(fā)送的消息 * @param flag 用來標識 是否要將消息推送給 當前用戶 */ public synchronized static void publicMessage(String userName,String message,boolean flag) { for (WebSocketUtil item : webSocketSet) { Session session = item.session; if (flag){ session.getAsyncRemote().sendText(message); }else { //獲取發(fā)送這條消息的用戶 Session currentUser = sessionMap.get(USER_NAME_PREFIX + userName); //消息不用推送到發(fā)送者的客戶端 if (!session.getId().equals(currentUser.getId())){ session.getAsyncRemote().sendText(message); } } } System.out.println("公共頻道接收了一條消息:"+message); } /** * 監(jiān)聽:連接成功 * @param session * @param userName 連接的用戶名 */ @OnOpen public void onOpen(Session session, @PathParam("userName") String userName) { this.userName = userName; this.session = session; sessionMap.put(USER_NAME_PREFIX + userName, session); webSocketSet.add(this); //在線數(shù)加1 String tips = userName+" 加入聊天室。當前聊天室人數(shù)為" + webSocketSet.size(); System.out.println(tips); publicMessage(userName,tips,true); } /** * 監(jiān)聽:收到客戶端發(fā)送的消息 * @param message 發(fā)送的信息(json格式,里面是 SocketMsg 的信息) */ @OnMessage public void onMessage(String message) { if (JSONUtil.isTypeJSONObject(message)) { SocketMsg socketMsg = JSONUtil.toBean(message, SocketMsg.class); if(socketMsg.getType() == 1){ //單聊,需要找到發(fā)送者和接受者 privateMessage(socketMsg); }else{ //群發(fā)消息 publicMessage(socketMsg.getSendOutUser(),socketMsg.getSendOutUser()+": "+socketMsg.getMsg(),false); } } } /** * 監(jiān)聽: 連接關閉 */ @OnClose public void onClose() { if (sessionMap.containsKey(USER_NAME_PREFIX + userName)) { //連接關閉后,將此websocket從set中刪除 sessionMap.remove(USER_NAME_PREFIX + userName); webSocketSet.remove(this); } String tips = userName+" 退出聊天室。當前聊天室人數(shù)為" + webSocketSet.size(); System.out.println(tips); publicMessage(userName,tips,true); } /** * 監(jiān)聽:發(fā)生異常 * @param error */ @OnError public void onError(Throwable error) { System.out.println("userName為:" + userName + ",發(fā)生錯誤:" + error.getMessage()); error.printStackTrace(); } }
?? 前端代碼
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>聊天室</title> <script src="https://code.jquery.com/jquery-3.3.1.min.js"></script> <style type="text/css"> input{ width: 150px; height: 30px; line-height: 25px; padding: 5px 10px; border-radius: 5px; border: 2px solid; font-size: 16px; } #msg{ width: 300px; } button{ width: 80px; height: 44px; padding: 5px 20px; border-radius: 5px; } </style> </head> <body> 聊天室<br/><br/> <input type="text" id="sendOutUser" placeholder="自己的用戶名"> <button onclick="connectWebSocket()">上線</button> <button onclick="closeWebSocket()">下線</button> <br/><br> <input type="text" id="msg" placeholder="要發(fā)送的信息"/> <input type="text" id="receiveUser" placeholder="接收人的用戶名"/> <button onclick="send()">發(fā)送</button> <br><br> <hr> <div id="msgList"></div> <script type="text/javascript"> var websocket = null; //連接WebSocket function connectWebSocket() { var sendOutUser = document.getElementById("sendOutUser").value; if (sendOutUser === "") { alert("請輸入用戶名"); return; } //判斷當前瀏覽器是否支持websocket if ('WebSocket' in window) { websocket = new WebSocket("ws://localhost:7070/web-socket/"+document.getElementById("sendOutUser").value); } else { alert('當前瀏覽器 not support websocket') } //連接發(fā)生錯誤的回調(diào)方法 websocket.onerror = function () { alert("連接發(fā)生錯誤"); }; //連接成功建立的回調(diào)方法 websocket.onopen = function () { var sendOutUser = document.getElementById("sendOutUser") sendOutUser.readOnly = true sendOutUser.style.backgroundColor='#ddd' } //接收到消息的回調(diào)方法 websocket.onmessage = function (event) { console.log(event.data) innerdiv("",event.data) } //連接關閉的回調(diào)方法 websocket.onclose = function () { innerdiv("","websocket連接關閉"); } //監(jiān)聽窗口關閉事件,當窗口關閉時,主動去關閉websocket連接,防止連接還沒斷開就關閉窗口,server端會拋異常。 window.onbeforeunload = function () { closewebsocket(); } } //關閉連接 function closeWebSocket() { websocket.close(); } //發(fā)送消息 function send() { var m = new Map(); // 空Map var sendOutId = document.getElementById("sendOutUser") //發(fā)送者 var msg = document.getElementById("msg").value //發(fā)送消息 if (msg === "") { alert("請輸入消息"); return; } var receiveUser = document.getElementById("receiveUser").value //接收者 m.set("sendOutUser",sendOutUser.value); m.set("msg",msg) // 接收者為空時,type為群聊,否則為私聊 if (receiveUser === "") { m.set("type",0) }else{ m.set("receiveUser",receiveUser) m.set("type",1) } json = mapToJson(m) websocket.send(json) innerdiv("我",msg) } //map轉(zhuǎn)換為json function mapToJson(map) { var obj= Object.create(null); for (var[k,v] of map) { obj[k] = v; } return JSON.stringify(obj); } //顯示聊天記錄到頁面 function innerdiv(id,txt){ var msgList = document.getElementById("msgList") if (id === "") { msgList.innerHTML += "<div>" + txt + "</div><br>" }else{ msgList.innerHTML += "<div>"+ id +": "+txt+ "</div><br>" } } </script> </body> </html>
到此這篇關于springboot結合websocket聊天室實現(xiàn)私聊+群聊的文章就介紹到這了,更多相關springboot websocket聊天室內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
您可能感興趣的文章:
- SpringBoot整合websocket實現(xiàn)即時通信聊天
- SpringBoot+WebSocket實現(xiàn)多人在線聊天案例實例
- SpringBoot中webSocket實現(xiàn)即時聊天
- Springboot+WebSocket實現(xiàn)一對一聊天和公告的示例代碼
- Springboot基于websocket實現(xiàn)簡單在線聊天功能
- SpringBoot+WebSocket搭建簡單的多人聊天系統(tǒng)
- SpringBoot+Websocket實現(xiàn)一個簡單的網(wǎng)頁聊天功能代碼
- SpringBoot結合WebSocket實現(xiàn)聊天功能
相關文章
springboot讀取application.yml報錯問題及解決
這篇文章主要介紹了springboot讀取application.yml報錯問題及解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-06-06pdf2swf+flexpapers實現(xiàn)類似百度文庫pdf在線閱讀
這篇文章主要介紹了pdf2swf+flexpapers實現(xiàn)類似百度文庫pdf在線閱讀的相關資料,需要的朋友可以參考下2014-10-10Java以編程方式實現(xiàn)JAR文件的創(chuàng)建
在這篇文章中,我們將為大家詳細介紹一下利用Java語言以編程方式創(chuàng)建jar文件的過程。文中的示例代碼講解詳細,感興趣的可以了解一下2022-07-07