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项目.点击加入群主,然后就可以发送消息了

相关推荐
明月_清风36 分钟前
DeepSeek Harness 安全审计实录:四个 PoC 揭露的 Agent 运行时"信任危机"
后端·安全·agent
苏三说技术1 小时前
再见了EasyExcel,我决定用Apache Fesod
后端
XR1234567881 小时前
医院移动医护零漫游无线网络选型指南
java·后端·struts
慧一居士1 小时前
Mybatis Plus中 LambdaQueryWrapper、QueryWrapper 区别对比
spring boot
干到60岁退休的码农1 小时前
13.构建登录接口响应数据
java·spring boot·mybatis
水巷石子1 小时前
学习langChain4j的第二天,体验springBoot中的starter
java·spring boot·学习·spring·langchain4j
ly76891 小时前
Spring Bean生命周期全流程:从BeanDefinition到销毁
java·后端·spring·bean生命周期·beandefinition·初始化回调
leeyi1 小时前
在 Go 里跑不信任的代码:WASM 沙箱的四道墙(第107篇)
后端
摇滚侠2 小时前
《Spring Boot 3:高级与架构设计》第 1 章 BeanDefinitionRegistry 阅读笔记 3
spring boot·笔记·后端
zhougl9962 小时前
Dockerfile实战教程
java·开发语言·spring boot