WebSocket實現聊天室業務
阿新 • • 發佈:2020-08-06
WebSocket實現聊天室業務的具體程式碼,供大家參考,具體內容如下
頁面效果圖
pom.xml
主要是spring-boot-starter-websocket包,websocket連線、傳送資訊。
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> <dependency><!--Webjars版本定位工具--> <groupId>org.webjars</groupId> <artifactId>webjars-locator-core</artifactId> </dependency> <dependency> <groupId>org.webjars.npm</groupId> <artifactId>mdui</artifactId> <version>0.4.0</version> </dependency> <dependency> <groupId>org.webjars</groupId> <artifactId>jquery</artifactId> <version>3.3.1</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.49</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency>
前臺
html + js
websocket 前臺主要包括四種方法:
- 開啟連線:onopen
- 服務端發來訊息:1.廣播訊息 2.更新線上人數 : onmessage
- 關閉連線 :onclose
- 通訊失敗 :onerror
<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> <title>WebSocket簡單聊天室</title> <meta charset="utf-8" name="viewport" content="width=device-width"> <link rel="stylesheet" th:href="@{/webjars/mdui/dist/css/mdui.css}"> <script th:src="@{/webjars/jquery/jquery.min.js}"></script> <script th:src="@{/webjars/mdui/dist/js/mdui.js}"></script> </head> <body class="mdui-theme-primary-indigo mdui-theme-accent-pink"> <div class="mdui-container"> <div class="mdui-toolbar mdui-color-theme"> <a class="mdui-btn mdui-btn-icon"><i class="mdui-icon material-icons">menu</i></a> <span class="mdui-typo-title">簡單聊天室</span> <div class="mdui-toolbar-spacer"></div> <a class="mdui-btn mdui-btn-icon" href="https://www.jianshu.com/p/964370d9374e" target="_blank"><i class="mdui-icon material-icons">search</i></a> <a class="mdui-btn mdui-btn-icon" th:href="@{/}"><i class="mdui-icon material-icons">exit_to_app</i></a> <a class="mdui-btn mdui-btn-icon"><i class="mdui-icon material-icons">more_vert</i></a> </div> </div> <div> <div class="mdui-container container_text"> <div class="mdui-row"> <div class="mdui-col-xs-12 mdui-col-sm-6"> <div class="mdui-col-xs-12 mdui-col-sm-10"> <div class="mdui-textfield-floating-label" style="margin-top:15px"> <i class="mdui-icon material-icons">歡迎:</i> <i class="mdui-icon" id="username" th:text="${username}"></i> </div> </div> <div class="mdui-col-xs-12 mdui-col-sm-10"> <div class="mdui-textfield mdui-textfield-floating-label"> <i class="mdui-icon material-icons">textsms</i> <label class="mdui-textfield-label">傳送內容</label> <input class="mdui-textfield-input" id="msg"/> </div> <div class="mdui-container" style="padding:20px 35px"> <button class="mdui-btn mdui-color-theme-accent mdui-ripple" onclick="sendMsgToServer()">傳送 (enter) </button> <button class="mdui-btn mdui-color-theme mdui-ripple" onclick="clearMsg()">清屏 </button> </div> </div> </div> <div class="mdui-col-xs-6 mdui-col-sm-5" style="padding:10px 0"> <div class="mdui-chip"> <span class="mdui-chip-icon mdui-color-blue"> <i class="mdui-icon material-icons"></i></span> <span class="mdui-chip-title">聊天內容</span> </div> <div class="mdui-chip"> <span class="mdui-chip-icon mdui-color-blue"> <i class="mdui-icon material-icons">face</i></span> <span class="mdui-chip-title">線上人數</span> <span class="mdui-chip-title chat-num">0</span> </div> <div class="message-container"> </div> </div> </div> </div> </div> <script th:inline="javascript"> /** * WebSocket客戶端 * * 使用說明: * 1、WebSocket客戶端通過回撥函式來接收服務端訊息。例如:webSocket.onmessage * 2、WebSocket客戶端通過send方法來發送訊息給服務端。例如:webSocket.send(); */ function getWebSocket() { /** * WebSocket客戶端 PS:URL開頭表示WebSocket協議 中間是域名埠 結尾是服務端對映地址 */ var webSocket = new WebSocket(/*[[${webSocketUrl}]]*/ 'ws://localhost:8080/chat'); /** * 當服務端開啟連線 */ webSocket.onopen = function (event) { console.log('WebSocket開啟連線'); }; /** * 當服務端發來訊息:1.廣播訊息 2.更新線上人數 */ webSocket.onmessage = function (event) { console.log('WebSocket收到訊息:%c' + event.data,'color:green'); //獲取服務端訊息 var message = JSON.parse(event.data) || {}; var $messageContainer = $('.message-container'); //喉嚨發炎 if (message.type === 'SPEAK') { $messageContainer.append( '<div class="mdui-card" style="margin: 10px 0;">' + '<div class="mdui-card-primary">' + '<div class="mdui-card-content message-content">' + message.username + ":" + message.msg + '</div>' + '</div></div>'); } $('.chat-num').text(message.onlineCount); //防止刷屏 var $cards = $messageContainer.children('.mdui-card:visible').toArray(); if ($cards.length > 5) { $cards.forEach(function (item,index) { index < $cards.length - 5 && $(item).slideUp('fast'); }); } }; /** * 關閉連線 */ webSocket.onclose = function (event) { console.log('WebSocket關閉連線'); }; /** * 通訊失敗 */ webSocket.onerror = function (event) { console.log('WebSocket發生異常'); }; return webSocket; } var webSocket = getWebSocket(); /** * 通過WebSocket物件傳送訊息給服務端 */ function sendMsgToServer() { var $message = $('#msg'); if ($message.val()) { webSocket.send(JSON.stringify({username: $('#username').text(),msg: $message.val()})); $message.val(null); } } /** * 清屏 */ function clearMsg() { $(".message-container").empty(); } /** * 使用ENTER傳送訊息 */ document.onkeydown = function (event) { var e = event || window.event || arguments.callee.caller.arguments[0]; e.keyCode === 13 && sendMsgToServer(); }; </script> </body> </html>
後臺
WebSocketChatApplication - 啟動類
@SpringBootApplication @RestController public class WebSocketChatApplication { /** * 登陸介面 */ @GetMapping("/") public ModelAndView login() { return new ModelAndView("/login"); } /** * 聊天介面 */ @GetMapping("/index") public ModelAndView index(String username,String password,HttpServletRequest request) throws UnknownHostException { if (StringUtils.isEmpty(username)) { username = "匿名使用者"; } ModelAndView mav = new ModelAndView("/chat"); mav.addObject("username",username); mav.addObject("webSocketUrl","ws://"+InetAddress.getLocalHost().getHostAddress()+":"+request.getServerPort()+request.getContextPath()+"/chat"); return mav; } public static void main(String[] args) { SpringApplication.run(WebSocketChatApplication.class,args); } }
WebSocketConfig - WebSocket配置類
@Configuration public class WebSocketConfig { /** * 用於掃描和註冊所有攜帶ServerEndPoint註解的例項。 * <p> * PS:若部署到外部容器 則無需提供此類。 */ @Bean public ServerEndpointExporter serverEndpointExporter() { return new ServerEndpointExporter(); } }
Message - 封裝資訊類
/** * WebSocket 聊天訊息類 */ public class Message { public static final String ENTER = "ENTER"; public static final String SPEAK = "SPEAK"; public static final String QUIT = "QUIT"; private String type;//訊息型別 private String username; //傳送人 private String msg; //傳送訊息 private int onlineCount; //線上使用者數 public static String jsonStr(String type,String username,String msg,int onlineTotal) { return JSON.toJSONString(new Message(type,username,msg,onlineTotal)); } public Message(String type,int onlineCount) { this.type = type; this.username = username; this.msg = msg; this.onlineCount = onlineCount; } public static String getENTER() { return ENTER; } public static String getSPEAK() { return SPEAK; } public static String getQUIT() { return QUIT; } public String getType() { return type; } public void setType(String type) { this.type = type; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getMsg() { return msg; } public void setMsg(String msg) { this.msg = msg; } public int getOnlineCount() { return onlineCount; } public void setOnlineCount(int onlineCount) { this.onlineCount = onlineCount; } }
WebSocketChatServer - 聊天服務端
前臺對應的四種傳輸,後臺進行處理操作
/** * WebSocket 聊天服務端 * * @see ServerEndpoint WebSocket服務端 需指定端點的訪問路徑 * @see Session WebSocket會話物件 通過它給客戶端傳送訊息 */ @Component @ServerEndpoint("/chat") public class WebSocketChatServer { /** * 全部線上會話 PS: 基於場景考慮 這裡使用執行緒安全的Map儲存會話物件。 */ private static Map<String,Session> onlineSessions = new ConcurrentHashMap<>(); /** * 當客戶端開啟連線:1.新增會話物件 2.更新線上人數 */ @OnOpen public void onOpen(Session session) { onlineSessions.put(session.getId(),session); sendMessageToAll(Message.jsonStr(Message.ENTER,"",onlineSessions.size())); } /** * 當客戶端傳送訊息:1.獲取它的使用者名稱和訊息 2.傳送訊息給所有人 * <p> * PS: 這裡約定傳遞的訊息為JSON字串 方便傳遞更多引數! */ @OnMessage public void onMessage(Session session,String jsonStr) { Message message = JSON.parseObject(jsonStr,Message.class); sendMessageToAll(Message.jsonStr(Message.SPEAK,message.getUsername(),message.getMsg(),onlineSessions.size())); } /** * 當關閉連線:1.移除會話物件 2.更新線上人數 */ @OnClose public void onClose(Session session) { onlineSessions.remove(session.getId()); sendMessageToAll(Message.jsonStr(Message.QUIT,onlineSessions.size())); } /** * 當通訊發生異常:列印錯誤日誌 */ @OnError public void onError(Session session,Throwable error) { error.printStackTrace(); } /** * 公共方法:傳送資訊給所有人 */ private static void sendMessageToAll(String msg) { onlineSessions.forEach((id,session) -> { try { session.getBasicRemote().sendText(msg); } catch (IOException e) { e.printStackTrace(); } }); } }
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援我們。