赞
踩
共开启两个页面,实现一对一聊天。
服务端代码:https://gitee.com/lianaozhe/springboot-websocket.git
导入相关依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
<!-- hutool 工具包,各种封装功能 一应俱全-->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.5</version>
</dependency>
WebSocketConfig配置类:
package com.web.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.socket.server.standard.ServerEndpointExporter; /** * @ClassName WebSocketConfig * @Description TODO * @Author laz * @Date 2023/4/26 16:18 * @Version 1.0 */ @Configuration public class WebSocketConfig { /** * 注入ServerEndpointExporter, * 这个bean会自动注册使用了@ServerEndpoint注解声明的Websocket endpoint */ @Bean public ServerEndpointExporter serverEndpointExporter() { return new ServerEndpointExporter(); } }
WebSocket操作类:
package com.web.websocket; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CopyOnWriteArraySet; import javax.websocket.*; import javax.websocket.server.PathParam; import javax.websocket.server.ServerEndpoint; import cn.hutool.json.JSONObject; import cn.hutool.json.JSONUtil; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; /** * @ClassName WebSocket * @Description TODO * @Author laz * @Date 2023/4/26 16:20 * @Version 1.0 */ @Component @Slf4j @ServerEndpoint("/websocket/{userId}") public class WebSocket { //与某个客户端的连接会话,需要通过它来给客户端发送数据 private Session session; /** * 用户ID */ private String userId; /** * 用来存放每个客户端对应的MyWebSocket对象。 */ private static CopyOnWriteArraySet<WebSocket> webSockets =new CopyOnWriteArraySet<>(); // 用来存在线连接用户信息 private static ConcurrentHashMap<String,Session> sessionPool = new ConcurrentHashMap<String,Session>(); /** * 链接成功调用的方法 */ @OnOpen public void onOpen(Session session, @PathParam(value="userId")String userId) { try { this.session = session; this.userId = userId; webSockets.add(this); sessionPool.put(userId, session); log.info("【websocket消息】有新的连接,用户id是【{}】总数为【{}】",userId,webSockets.size()); } catch (Exception e) { } } /** * 链接关闭调用的方法 */ @OnClose public void onClose() { try { webSockets.remove(this); sessionPool.remove(this.userId); log.info("【websocket消息】连接断开,总数为:"+webSockets.size()); } catch (Exception e) { } } /** * 收到客户端消息后调用的方法 * * @param message * @param message */ @OnMessage public void onMessage(String message) { log.info("【websocket消息】收到客户端消息:"+message); JSONObject jsonObject = JSONUtil.parseObj(message); Object toUserId = jsonObject.get("toUserId"); Session session = sessionPool.get(toUserId); session.getAsyncRemote().sendText(JSONUtil.toJsonStr(jsonObject.get("msg"))); } /** 发送错误时的处理 * @param session * @param error */ @OnError public void onError(Session session, Throwable error) { log.error("用户错误,原因:"+error.getMessage()); error.printStackTrace(); } // 此为广播消息 public void sendAllMessage(String message) { log.info("【websocket消息】广播消息:"+message); for(WebSocket webSocket : webSockets) { try { if(webSocket.session.isOpen()) { webSocket.session.getAsyncRemote().sendText(message); } } catch (Exception e) { e.printStackTrace(); } } } // 此为单点消息 public void sendOneMessage(String userId, String message) { Session session = sessionPool.get(userId); if (session != null&&session.isOpen()) { try { log.info("【websocket消息】 单点消息:"+message); session.getAsyncRemote().sendText(message); } catch (Exception e) { e.printStackTrace(); } } } // 此为单点消息(多人) public void sendMoreMessage(String[] userIds, String message) { for(String userId:userIds) { Session session = sessionPool.get(userId); if (session != null&&session.isOpen()) { try { log.info("【websocket消息】 单点消息:"+message); session.getAsyncRemote().sendText(message); } catch (Exception e) { e.printStackTrace(); } } } } }
TestController测试接口类:
package com.web.controller; import com.web.websocket.WebSocket; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; /** * @ClassName TestController * @Description TODO * @Author laz * @Date 2023/4/26 16:23 * @Version 1.0 */ @RestController @RequestMapping("web") public class TestController { @Autowired private WebSocket webSocket; @RequestMapping("test") public String test(String userId,String msg){ webSocket.sendOneMessage(userId,msg); return "成功"; } }
test.html文件:
<!doctype html> <html lang="zh-CN"> <head> <!-- 必须的 meta 标签 --> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <!-- Bootstrap 的 CSS 文件 --> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/css/bootstrap.min.css" integrity="sha384-xOolHFLEh07PJGoPkLv1IbcEPTNtaed2xpHsD9ESMhqIYd0nLMwNLD69Npy4HI+N" crossorigin="anonymous"> <title>WebSocket1</title> <style> form { width: 820px; margin: auto; } .div1 { width: 820px; height: 500px; border: #000000; border-width: thin; border-style: solid; } .div2 { text-align: center; width: 800px; height: 50px; } </style> <script> function clearData() { $("#div1").html(""); } var socket; function openSocket() { if (typeof(WebSocket) == "undefined") { console.log("您的浏览器不支持WebSocket"); } else { console.log("您的浏览器支持WebSocket"); //websocket地址 var socketUrl = "ws://localhost:8088/websocket/20"; console.log(socketUrl); if (socket != null) { socket.close(); socket = null; } socket = new WebSocket(socketUrl); //打开事件 socket.onopen = function() { console.log("websocket已打开"); $("#div1").append("websocket已打开" + "<br \>"); }; //获得消息事件 socket.onmessage = function(msg) { console.log(msg.data); $("#div1").append("接收到消息:" + msg.data + "<br \>"); }; //关闭事件 socket.onclose = function() { console.log("websocket已关闭"); $("#div1").append("websocket已关闭" + "<br \>"); }; //发生了错误事件 socket.onerror = function() { console.log("websocket发生了错误"); $("#div1").append("websocket发生了错误" + "<br \>"); } } } function sendMsg() { if (typeof(WebSocket) == "undefined") { console.log("您的浏览器不支持WebSocket"); } else { console.log("您的浏览器支持WebSocket"); console.log('{"toUserId":"' + $("#toUserId").val() + '","msg":"' + $("#msg").val() + '"}'); socket.send('{"toUserId":"' + $("#toUserId").val() + '","msg":"' + $("#msg").val() + '"}'); var msg = document.getElementById("msg").value; $("#div1").append("发送消息:" + msg + "<br \>"); document.getElementById("msg").value = ""; } } </script> </head> <body> <h1 align="center">WebSocket测试Demo</h1><br /> <form class="form-inline"> <div class="form-group mx-sm-3 mb-2"> <label for="toUserId" class="sr-only">toUserId</label> <input type="text" class="form-control" id="toUserId" placeholder="toUserId"> </div> <div class="form-group mb-2"> <label for="msg" class="sr-only">消息內容</label> <input type="text" class="form-control" id="msg" placeholder="消息內容"> </div> <div class="form-group mx-sm-3 mb-2"> <button type="button" class="btn btn-primary" onclick="openSocket()">开启socket</button> </div> <div class="form-group mx-sm-3 mb-2"> <button type="button" class="btn btn-danger" onclick="sendMsg()">发送消息</button> </div> <div class="form-group mx-sm-3 mb-2"> <button type="button" class="btn btn-secondary" onclick="clearData()">清空内容</button> </div> <div class="div2"></div> <div class="div1" id="div1"></div> </form> </body> <script src="https://cdn.jsdelivr.net/npm/jquery@3.5.1/dist/jquery.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"> </script> <script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-7ymO4nGrkm372HoSbq1OY2DP4pEZnMiA+E0F3zPr+JQQtQ82gQ1HPY3QIVtztVua" crossorigin="anonymous"> </script> </html>
复制test.html文件为test2.html文件,将上面的userId由’20’改为’10’,后面测试使用。
运行服务端项目,打开test.html,点击’开启socket’按钮(一定要先开启socket连接,否则无法接收到消息)。
可以看到,服务端与客户端已建立了连接。
然后调用我们的测试接口:
然后观察test.html页面:
可以看到,客户端的用户20成功接收到服务端发来的信息。
打开test2.html,同样点击’开启socket’,与服务端建立连接。
此时用test2.html给test.html发送一条消息。
可以看到,此时两个页面直接已经可以进行一对一的聊天了。
代码已上传到git:https://gitee.com/lianaozhe/springboot-websocket.git
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。