Spring boot WebSocket实现简单的多人聊天
程序员文章站
2022-07-10 18:57:14
WebSocket + Spring boot 实现简单的多人聊天直接上代码:HTML + JS 前端部分这里的WebSocket对象是关键,其他没啥说的。
WebSocket + Spring boot 实现简单的多人聊天
直接上代码:
HTML + JS 前端部分
这里的WebSocket
对象是关键,其他没啥说的。
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> </head> <body> <input type="number" name="" id="id_input" value="" placeholder="用户ID(数字)" /> <button id="key">连接</button> <br /> <input type="text" name="" id="msg_input" value="" /> <button id="send">发送</button> <div id="msgbox"> <!-- 用来接受显示服务端发来的消息 --> </div> <script type="text/javascript"> var btn = document.getElementById("key"); var send = document.getElementById("send"); var msgbox = document.getElementById("msgbox"); btn.onclick = function() { if ("WebSocket" in window) { console.log("您的浏览器支持 WebSocket!"); // 打开一个 web socket并携带这用户ID的参数 var ws = new WebSocket("ws://127.0.0.1:8999/chat/" + document.getElementById("id_input").value); ws.onopen = function() { // Web Socket 已连接上,使用 send() 方法发送数据 console.log("连接成功..."); }; send.onclick = function() { ws.send(document.getElementById("msg_input").value); } ws.onmessage = function(evt) { //将数据回显到界面上 msgbox.innerHTML = msgbox.innerHTML + "<br/>" + evt.data; }; ws.onclose = function() { // 关闭 websocket console.log("连接已关闭..."); }; } else { // 浏览器不支持 WebSocket console.log("您的浏览器不支持 WebSocket!"); } } </script> </body> </html>
Springboot后端部分
1. pom.xml
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>godkai.xyz</groupId> <artifactId>websocketTest</artifactId> <version>1.0-SNAPSHOT</version> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.3.1.RELEASE</version> </parent> <dependencies> <!--spring-boot starters--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> </dependency> </dependencies> </project>
2. yml配置文件
server: port: 8999
3. 配置ServerEndpointExporter的Bean,让Springboot支持WebSocket
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(); } }
4. 消息处理类(重点)
这里我个人理解是每有一个websocket的连接请求服务端会创建一个这个我写的对象ChatSocketEntity
前端那里:
"ws://127.0.0.1:8999/chat/{userId}"
这个类上:@ServerEndpoint("/chat/{userId}")
来控制每个websocket的事件监听,分别是
@OnOpen
建立连接时调用的方法@OnClose
收到客户端消息后调用的方法@OnMessage
连接关闭时调用的方法@OnError
发生错误时调用的方法
使用一个静态的Map来储存当前已经连接的用户,当然我觉得这个Map可以用任意容器来代替(Redis?)。
private static Map<Integer, ChatSocketEntity> onlineUserMap = new ConcurrentHashMap<Integer, ChatSocketEntity>();
这几个注解对应的方法。
其中private Session session
属性对应的是服务端与客户端的一个会话对象。
我理解成 在服务端的角度看 session 就是与客户端的一个TCP长连接,而我自己的ChatSocketEntity类就是用来控制这个 session 的生命周期的类。
代码:
import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; import javax.websocket.*; import javax.websocket.server.PathParam; import javax.websocket.server.ServerEndpoint; import java.io.IOException; import java.util.Collection; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; @Component @ServerEndpoint("/chat/{userId}") @Slf4j public class ChatSocketEntity{ //用来保存所有已经连接上的ChatSocketEntity private static Map<Integer, ChatSocketEntity> onlineUserMap = new ConcurrentHashMap<Integer, ChatSocketEntity>(); private Integer userId; private Session session; @OnOpen public void onOpen(@PathParam("userId") Integer userId, Session session) { //判断用户ID已经连接过 ChatSocketEntity chatSocketEntity = ChatSocketEntity.onlineUserMap.get(userId); if (chatSocketEntity != null) { try { sendMessage("用户已在其他地方连接,您*下线", chatSocketEntity.session); chatSocketEntity.session.close(); } catch (IOException e) { e.printStackTrace(); } } //保存用户连接的信息 this.userId = userId; this.session = session; ChatSocketEntity.onlineUserMap.put(userId, this); log.info("user:" + userId + " is online!!!" + "|online count: " + onlineUserMap.size()); } /**
* 连接关闭调用的方法
*/ @OnClose public void onClose() { ChatSocketEntity.onlineUserMap.remove(this.userId); log.info("user:" + this.userId + " is leave!!!" + "|online count: " + onlineUserMap.size()); } /**
* 收到客户端消息后调用的方法
*/ @OnMessage public void onMessage(String message) { Collection<ChatSocketEntity> values = onlineUserMap.values(); values.forEach(x -> { try { sendMessage(this.userId + ": " + message, x.session); } catch (IOException e) { e.printStackTrace(); } }); log.info("user:" + this.userId + " say: " + message); } /**
* 发生错误时调用
*/ @OnError public void onError(Session session, Throwable error) { System.out.println("发生错误!!!"); error.printStackTrace(); } /**
* 根据session向客户端发送消息
*/ public static void sendMessage(String message, Session session) throws IOException { session.getBasicRemote().sendText(message); } }
总结
前端用 WebSocket 对象进行信息交互
后端用 ChatSocketEntity(需要自定义) 类的对象包裹着 javax.websocket.Session类的对象 来进行交互
本文地址:https://blog.csdn.net/kaiforth/article/details/108251125
上一篇: Spring框架核心讲解
推荐阅读
-
最简单的spring boot打包docker镜像的实现
-
基于SpringBoot+WebSocket搭建一个简单的多人聊天系统
-
Spring Boot实现STOMP协议的WebSocket的方法步骤
-
spring boot websocket stomp 实现广播通信和一对一通信聊天
-
Spring Boot实现简单的定时任务
-
Spring boot WebSocket实现简单的多人聊天
-
spring boot1.1 idea + springboot + mybatis(mybatis-generator) +mysql +html实现简单的登录注册
-
基于SpringBoot+WebSocket搭建一个简单的多人聊天系统
-
Spring Boot+JWT快速实现简单的接口鉴权
-
golang实现一个简单的websocket聊天室功能