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

发布于:2024-06-28 ⋅ 阅读:(11) ⋅ 点赞:(0)
  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项目.点击加入群主,然后就可以发送消息了


网站公告

今日签到

点亮在社区的每一天
去签到