ThinkChat🤖让你学习和工作更高效,注册即送10W Token,即刻开启你的AI之旅 广告
[TOC] # 简介 springboot的组件`spring-boot-starter-websocket` ~~~ <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> </dependency> ~~~ | 事件 | 事件处理程序 | 描述 | | --- | --- | --- | | open | Socket onopen | 连接建立时触发 | | message | Socket onmessage | 客户端接收服务端数据时触发 | | error | Socket onerror | 通讯发生错误时触发 | | close | Socket onclose | 链接关闭时触发 | ~~~ var ws = new WebSocket("ws://localhost:8080"); ws.onopen = function(evt) { console.log("Connection open ..."); ws.send("Hello WebSockets!"); }; ws.onmessage = function(evt) { console.log( "Received Message: " + evt.data); ws.close(); }; ws.onclose = function(evt) { console.log("Connection closed."); }; ~~~ # 聊天室 ## 前端 * 加入聊天室,是建立连接onopen * 退出聊天室, 关闭连接onclose * 发送消息,调用onmessage * 异常时退出,对应onerror ~~~ <!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>聊天室</title> <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script> <link href="//cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"> <!-- <link href="//cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.css" rel="stylesheet">--> </head> <body class="container" style="width: 60%"> <div class="form-group" ></br> <h5>聊天室</h5> <textarea id="message_content" class="form-control" readonly="readonly" cols="50" rows="10"></textarea> </div> <div class="form-group" > <label for="in_user_name">用户姓名 &nbsp;</label> <input id="in_user_name" value="" class="form-control" /></br> <button id="user_join" class="btn btn-success" >加入聊天室</button> <button id="user_exit" class="btn btn-warning" >离开聊天室</button> </div> <div class="form-group" > <label for="in_room_msg" >群发消息 &nbsp;</label> <input id="in_room_msg" value="" class="form-control" /></br> <button id="user_send_all" class="btn btn-info" >发送消息</button> </div> </body> <script type="text/javascript"> $(document).ready(function(){ var urlPrefix ='ws://localhost:8085/chat-room/'; var ws = null; $('#user_join').click(function(){ var username = $('#in_user_name').val(); if(username==''){ alert("请输入用户名!"); return; } 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 连接..."); } }); //客户端发送消息到服务器 $('#user_send_all').click(function(){ var msg = $('#in_room_msg').val(); if(msg==''){ alert("请填写消息!"); return; } if(ws && msg!=''){ ws.send(msg); } }); // 退出聊天室 $('#user_exit').click(function(){ if(ws){ ws.close(); } }); }) </script> </html> ~~~ ## 启动类 ~~~ @EnableWebSocket @SpringBootApplication public class UserApplication { public static void main(String[] args) { ApplicationContext context = SpringApplication.run(UserApplication.class, args); } @Bean public ServerEndpointExporter serverEndpointExporter() { return new ServerEndpointExporter(); } ~~~ ## websocket工具类 ~~~ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.websocket.RemoteEndpoint; import javax.websocket.Session; import java.io.IOException; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; public final class WebSocketUtils { private static final Logger logger = LoggerFactory.getLogger(WebSocketUtils.class); //存储websocket session,在线用户 public static final Map<String, Session> ONLINE_USER_SESSIONS = new ConcurrentHashMap<>(); /** * @param session 用户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 (IOException e) { logger.error("send message exception ", e); } } /** * 聊天室消息,所有用户可见,每次消息触发就是遍历所有在线用户,给每个用户发消息 * @param message */ public static void sendMessageAll(String message) { ONLINE_USER_SESSIONS.forEach((sessionId, session) -> sendMessage(session, message)); } } ~~~ ## websocket接收地址处理类 先导入工具类的这个2个静态 ~~~ import static com.jdxia.user.utils.WebSocketUtils.ONLINE_USER_SESSIONS; import static com.jdxia.user.utils.WebSocketUtils.sendMessageAll; ~~~ 写处理程序 ~~~ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.web.bind.annotation.RestController; import javax.websocket.*; import javax.websocket.server.PathParam; import javax.websocket.server.ServerEndpoint; import java.io.IOException; import static com.jdxia.user.utils.WebSocketUtils.ONLINE_USER_SESSIONS; import static com.jdxia.user.utils.WebSocketUtils.sendMessageAll; @RestController @ServerEndpoint("/chat-room/{username}") //表示监听这个地址的websocket信息 public class ChatRoomServerEndpoint { private static final Logger logger = LoggerFactory.getLogger(ChatRoomServerEndpoint.class); @OnOpen public void openSession(@PathParam("username") String username, Session session) { //用户登录的时候,把用户信息放入session中 ONLINE_USER_SESSIONS.put(username, session); String message = "欢迎用户[" + username + "]来到聊天室"; logger.info("用户登录: " + message); sendMessageAll(message); } //监听发送消息事件 @OnMessage public void onMessage(@PathParam("username") String username, String message) { logger.info("发送消息: " + message); sendMessageAll("用户[" + username + "] : " + message); } @OnClose public void onClose(@PathParam("username") String username, Session session) { //当前session移除 ONLINE_USER_SESSIONS.remove(username); //并且通知他人退出 sendMessageAll("用户[" + username + "] 已经离开聊天室"); try { session.close(); } catch (IOException e) { logger.error("onClose error: ", e); } } @OnError public void onError(Session session, Throwable throwable) { try{ session.close(); } catch (IOException e) { logger.error("onError exception: ", e); } logger.info("Throwable msg: " + throwable.getMessage()); } } ~~~