spring boot整合WebSocket实现群聊功能 通俗易懂教程

  1. 首先获取消息的内容,即payload。
  2. 将payload转换为JSONObject对象,并从中获取消息类型type。
  3. 如果消息类型是"join",则从消息中获取群组ID,并将当前WebSocketSession的ID加入到该群组对应的Set中。
  4. 如果消息类型是"leave",则从消息中获取群组ID,并从该群组对应的Set中移除当前WebSocketSession的ID。
  5. 如果消息类型是"message",则从消息中获取群组ID,并获取该群组对应的所有WebSocketSession,逐一向这些Session发送消息。

其中,groups和sessions是两个Map,分别用来存储群组与其对应的WebSocketSessions。computeIfAbsent和computeIfPresent方法分别用来向Map中添加元素和更新元素。sendMessage方法用来向客户端发送消息。

导入依赖

复制代码
        <!-- spring-boot-starter-websocket依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-websocket</artifactId>
        </dependency>
创建MyWebSocketHandler类
复制代码
import com.songzixain.service.MyWebSocketHandler;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;

/**
 * <p>
 * Description: WebSocketConfig配置类
 * </p>
 *
 * @author 
 * @version 
 * @create 
 * @see 
 */

@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {

    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
        registry.addHandler(new MyWebSocketHandler(), "/ws").setAllowedOrigins("*");
创建MyWebSocketHandler类

这段代码是一个WebSocket处理器中的消息处理方法,用来处理WebSocket客户端发送的消息

复制代码
/**
 * <p>
 * Description: MyWebSocketHandler用 来处理WebSocket客户端发送的消息
 * </p>
 *
 * @author 
 * @version 
 * @create 
 * @see 
 */
@Slf4j
public class MyWebSocketHandler implements WebSocketHandler {

    private static final Map<String, WebSocketSession> sessions = new ConcurrentHashMap<>();
    private static final Map<String, Set<String>> groups = new ConcurrentHashMap<>();

    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        sessions.put(session.getId(), session);
    }


    @Override
    public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) throws Exception {
        String payload = message.getPayload().toString();
        log.info("接收到的用户消息 {}", payload);
        JSONObject json = JSON.parseObject(payload);

        String type = json.getString("type");
        //  用户加入了群组
        if ("join".equals(type)) {
            String groupId = json.getString("groupId");
            groups.computeIfAbsent(groupId, k -> new HashSet<>()).add(session.getId());
        } else if ("leave".equals(type)) {
            String groupId = json.getString("groupId");
            groups.computeIfPresent(groupId, (k, v) -> {
                v.remove(session.getId());
                return v;
            });
            // 接收到了用户消息
        } else if ("message".equals(type)) {
            String groupId = json.getString("groupId");
            Set<String> groupSessions = groups.get(groupId);
            for (String sessionId : groupSessions) {
                WebSocketSession s = sessions.get(sessionId);
                if (s != null && s.isOpen()) {
                    s.sendMessage(new TextMessage(payload));
                }
            }
        }
    }

    @Override
    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
        sessions.remove(session.getId());
    }

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception {
        sessions.remove(session.getId());
        groups.values().forEach(v -> v.remove(session.getId()));
    }

    @Override
    public boolean supportsPartialMessages() {
        return false;
    }
}
前端的html测试页面
复制代码
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>WebSocket Chat</title>
</head>
<body>
    <div id="output"></div>
    <input id="input" type="text" placeholder="Type your message">
    <button id="send">Send</button>
    <button id="join">Join Group</button>
    <button id="leave">Leave Group</button>

    <script>
        var socket = new WebSocket("ws://localhost:8080/ws");

        socket.onopen = function(event) {
            console.log("WebSocket connected");
        };

        socket.onmessage = function(event) {
            var message = event.data;
            var output = document.getElementById("output");
            var p = document.createElement("p");
            p.innerText = message;
            output.appendChild(p);
        };

        socket.onclose = function(event) {
            console.log("WebSocket disconnected");
        };

        var sendButton = document.getElementById("send");
        var input = document.getElementById("input");
        var joinButton = document.getElementById("join");
        var leaveButton = document.getElementById("leave");

        sendButton.addEventListener("click", function() {
            var message = {
                userId: "1",
                type: "message",
                groupId: "group1",
                content: input.value
            };
            socket.send(JSON.stringify(message));
            input.value = "";
        });

        joinButton.addEventListener("click", function() {
            var message = {
                userId: "1",
                type: "join",
                groupId: "group1"
            };
            socket.send(JSON.stringify(message));
        });

        leaveButton.addEventListener("click", function() {
            var message = {
                userId: "1",
                type: "leave",
                groupId: "group1"
            };
            socket.send(JSON.stringify(message));
        });
        socket.onmessage = function(event) {
    var message = event.data;
    var output = document.getElementById("output");
    var p = document.createElement("p");
    p.innerText = message;
    output.appendChild(p);
};
    </script>
</body>
</html>

这个WebSocket处理器实现了群聊功能,并支持用户加入和离开群组时向群组中的其他用户发送通知。

启动Spring Boot项目.点击加入群主,然后就可以发送消息了

相关推荐
IT_陈寒1 小时前
闭包陷阱让我加了两天班,JavaScript你真行
前端·人工智能·后端
易协同低代码2 小时前
通达OA核心类库TD类深度解析
后端
Gopher_HBo2 小时前
Go语言学习笔记(十八)Gin处理Session
后端
谭光志3 小时前
工具塞满上下文窗口怎么办?深度拆解 AI Agent Tool Search 按需加载实现原理
前端·后端·ai编程
她说..3 小时前
Java 默认值设置方式
java·开发语言·后端·springboot
foggyprojects3 小时前
从0开始,一句话启动AI DataAgent
后端·数据分析·ai编程
郡杰3 小时前
一些基础和问题解决
后端
陈随易4 小时前
前端项目部署只要30秒
前端·后端·程序员
YIAN4 小时前
从零手写文件读取 MCP 服务:一文吃透 Model Context Protocol 全链路通信原理
前端·后端·mcp
Imchendiana4 小时前
《狂人日记NO.9》— 前后端一把梭,我的全栈实录
前端·后端