一、添加依賴javascript
<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>
二、添加工具類html
package com.example.demo.utils; import javax.websocket.RemoteEndpoint; import javax.websocket.Session; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; public final class WebSocketUtils { /** * 模擬存儲websocket session */ public static final Map<String, Session> LIVING_SESSION_CACHE = new ConcurrentHashMap(); public static void sendMessageAll(String message){ LIVING_SESSION_CACHE.forEach((sessionId,session) -> sendMessage(session,message)); } /** * 發送給指定用戶 * @param session * @param message */ public static void sendMessage(Session session, String message){ if(session == null){ return; } final RemoteEndpoint.Basic basic = session.getBasicRemote(); if(basic == null){ return; } try { basic.sendText(message); }catch (Exception e){ e.printStackTrace(); } } }
三、添加服務站點java
主要使用註解以下:jquery
@ServerEndpoint:聊天室訪問地址web
@OnOpen: 創建 WebSocket 鏈接時觸發spring
@OnMessage:客戶端監聽服務端事件,當服務端向客戶端推送消息時會被監聽到服務器
@OnClose:關閉 WebSocket 鏈接時觸發websocket
@OnError:發生錯誤時觸發session
@GetMapping:接收消息請求地址app
其中@ServerEndpoint 中的內容就是 WebSocket 協議的地址,其實仔細看會發現與 @RequestMapping 也是殊途同歸的… HTTP 協議:http://localhost:8080/path WebSocket 協議:ws://localhost:8080/path
package com.example.demo.controller; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.web.bind.annotation.*; import javax.websocket.*; import javax.websocket.server.PathParam; import javax.websocket.server.ServerEndpoint; import static com.example.demo.utils.WebSocketUtils.LIVING_SESSION_CACHE; import static com.example.demo.utils.WebSocketUtils.sendMessage; import static com.example.demo.utils.WebSocketUtils.sendMessageAll; @RestController @ServerEndpoint("/chat-room/{username}") public class SocketController { private static final Logger log = LoggerFactory.getLogger(SocketController.class); @OnOpen public void openSession(@PathParam("username") String name, Session session){ LIVING_SESSION_CACHE.put(name,session); String message = "歡迎用戶["+ name + "]來到朦朧的夜聊天室"; log.info(message); sendMessageAll(message); } @OnMessage public void onMessage(@PathParam("username") String username, String message){ log.info(message); sendMessageAll("用戶["+username+"]:" + message); } @OnClose public void onClose(@PathParam("username") String username, Session session){ //移除session LIVING_SESSION_CACHE.remove(username); //通知他人 sendMessageAll("用戶["+username+"]已經離開朦朧的夜聊天室"); try { session.close(); }catch (Exception e){ e.printStackTrace(); } } @OnError public void onError(Session session,Throwable throwable){ try { session.close(); }catch (Exception e){ e.printStackTrace(); } throwable.printStackTrace(); } @GetMapping("/chat-room/{sender}/to/{receive}") public void onMessage(@PathVariable("sender") String sender,@PathVariable("receive") String receive, String message){ sendMessage(LIVING_SESSION_CACHE.get(receive),"["+sender+"]:"+message); } }
四、添加聊天室html
此處注意一點,要添加引入jquery
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>battcn websocket</title> <script src="/jquery-3.4.1.min.js" ></script> </head> <body> <label for="message_content">聊 天 室 </label><textarea id="message_content" readonly="readonly" cols="57" rows="10"> </textarea> <br/> <label for="in_user_name">用戶姓名 </label><input id="in_user_name" value=""/> <button id="btn_join">加入聊天室</button> <button id="btn_exit">離開聊天室</button> <br/><br/> <label for="in_room_msg">羣發消息 </label><input id="in_room_msg" value=""/> <button id="btn_send_all">發送消息</button> <br/><br/><br/> 好友聊天 <br/> <label for="in_sender">發送者 </label><input id="in_sender" value=""/><br/> <label for="in_receive">接受者 </label><input id="in_receive" value=""/><br/> <label for="in_point_message">消息體 </label><input id="in_point_message" value=""/><button id="btn_send_point">發送消息</button> </body> <script type="text/javascript"> $(document).ready(function(){ var urlPrefix ='ws://localhost:8080/chat-room/'; var ws = null; $('#btn_join').click(function(){ var username = $('#in_user_name').val(); var url = urlPrefix + username; ws = new WebSocket(url); ws.onopen = function () { console.log("創建 websocket 鏈接..."); }; ws.onmessage = function(event){ //服務端發送的消息 $('#message_content').append(event.data+'\n'); }; ws.onclose = function(){ $('#message_content').append('用戶['+username+'] 已經離開聊天室!'); console.log("關閉 websocket 鏈接..."); } }); //客戶端發送消息到服務器 $('#btn_send_all').click(function(){ var msg = $('#in_room_msg').val(); if(ws){ ws.send(msg); } }); // 退出聊天室 $('#btn_exit').click(function(){ if(ws){ ws.close(); } }); $("#btn_send_point").click(function() { var sender = $("#in_sender").val(); var receive = $("#in_receive").val(); var message = $("#in_point_message").val(); $.get("/chat-room/"+sender+"/to/"+receive+"?message="+message,function() { alert("發送成功...") }) }) }) </script> </html>
五、主函數
@Bean public ServerEndpointExporter serverEndpointExporter(){ return new ServerEndpointExporter(); }
六、添加入口方法
@GetMapping(value ="/sockethtml") public String sockethtml(){ return "lliaotianshi"; }
七、測試
http://localhost:8080/test/sockethtml