欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

相关标签: java websocket