SpringBoot整合WebSocket实现聊天室

1.简单的实现了聊天室功能,注意页面刷新后聊天记录不会保存,后端没有做消息的持久化

2.后端用户的识别只简单使用Session用户的身份

0.依赖

XML 复制代码
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-websocket</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

1.配置WebSocketConfigurer配置类

java 复制代码
package com.example.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.http.server.ServletServerHttpRequest;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;
import org.springframework.web.socket.server.HandshakeInterceptor;

import javax.servlet.http.HttpSession;
import java.util.Map;

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfigurer implements WebSocketMessageBrokerConfigurer {

    @Override
    public void configureMessageBroker(MessageBrokerRegistry config) {
        config.enableSimpleBroker("/topic");
        config.setApplicationDestinationPrefixes("/app");
    }

    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        registry.addEndpoint("/ws").withSockJS()
                .setInterceptors(new HttpHandshakeInterceptor());
    }

    public class HttpHandshakeInterceptor implements HandshakeInterceptor {
        @Override
        public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response,
                                       WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception {
            if (request instanceof ServletServerHttpRequest) {
                ServletServerHttpRequest servletRequest = (ServletServerHttpRequest) request;
                HttpSession session = servletRequest.getServletRequest().getSession(false);
                if (session != null) {
                    //使用session中的user
                    String user = (String) session.getAttribute("user");
                    if(user!=null){
                        attributes.put("user", user);
                    }
                }
            }
            return true;
        }

        @Override
        public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response,
                                   WebSocketHandler wsHandler, Exception exception) { }
    }

}

2.MessageHandler用于处理接收消息

java 复制代码
package com.example.webController;

import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.messaging.simp.SimpMessageHeaderAccessor;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

import javax.servlet.http.HttpSession;

@Controller
public class MessageHandler {


    @MessageMapping("/chat")
    @SendTo("/topic/messages")
    public String chat(@PathVariable("messages") String message, SimpMessageHeaderAccessor headerAccessor) {
        // 获取用户数据
        Object user = headerAccessor.getSessionAttributes().get("user");
        System.out.println("User: " + user);

        return user.toString()+":" + message;
    }

    //登录
    @GetMapping("login/{userName}")
    public void login(@PathVariable String userName, HttpSession session) {
        System.out.println("User " + userName);
        session.setAttribute("user", userName);
    }
}

3.前端页面

先登录后发送消息

4.前端代码

html 复制代码
<!DOCTYPE html>
<html>
<head>
    <title>WebSocket Demo</title>
    <script src="https://cdn.jsdelivr.net/npm/sockjs-client/dist/sockjs.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/stompjs/lib/stomp.min.js"></script>
    <style>
        #chatBox {
            width: 60%;
            margin: auto;
            height: 500px;
            border: 1px solid black;
            padding: 10px;
            border-radius: 7px;
        }
        .chat-message {
            height: 85%;
            overflow: auto;
        }
        .flex-row, .flex-row-reverse {
            display: flex;
            justify-content: space-between;
            padding: 10px 0;
        }
        .message {
            max-width: 60%;
            padding: 10px;
            border-radius: 10px;
        }
        .user {
            background-color: #7986cb;
            color: white;
        }
        .assistant {
            background-color: #ffe082;
        }
        #inputMessage {
            width: 80%;
            padding: 10px;
            border-radius: 10px;
            border: 1px solid black;
            margin-top: 10px;
        }
        #sendButton {
            width: 15%;
            margin-left: 5%;
            padding: 11px;
            background-color: #ff7043;
            color: white;
            border: none;
            border-radius: 10px;
            cursor: pointer;
        }
    </style>
</head>
<body>
<div id="chat">
    <div id="chatBox">
        <div class="chat-message">
            <div class="flex-row">
                <div class="message user">
                    <p>Hello</p>
                </div>
            </div>
            <div class="flex-row-reverse">
                <div class="message assistant">
                    <p>Hi, How can I help you?</p>
                </div>
            </div>
        </div>
        <input type="text" id="inputMessage" placeholder="Type message.." />
        <button id="sendButton"  onclick="send()">Send</button>
    </div>
    <input type="text" id="login" placeholder="输入用户名。。。" />
    <button  onclick="login()">Login</button>

</div>
<script>
    var socket = new SockJS('/ws');
    var stompClient = Stomp.over(socket);

    stompClient.connect({}, function(frame) {
        stompClient.subscribe('/topic/messages', function(message) {
            var div = document.createElement('div');
            div.className = "flex-row-reverse";
            var messageDiv = document.createElement('div');
            messageDiv.className = "message assistant";
            var p = document.createElement('p');
            p.textContent = message.body;
            messageDiv.appendChild(p);
            div.appendChild(messageDiv);
            document.querySelector('.chat-message').appendChild(div);
        });
    });
    function login() {
        var value = document.getElementById('login').value;
        //发送get请求
        fetch('/login/' + value)
        //刷新页面
        window.location.reload();
    }
    function send() {
        var inputValue = document.getElementById('inputMessage').value;
        var div = document.createElement('div');
        div.className = "flex-row";
        // var messageDiv = document.createElement('div');
        // messageDiv.className = "message user";
        // var p = document.createElement('p');
        // p.textContent = inputValue;
        // messageDiv.appendChild(p);
        // div.appendChild(messageDiv);
        document.querySelector('.chat-message').appendChild(div);
        stompClient.send("/app/chat", {}, inputValue);
        document.getElementById('inputMessage').value = '';
    }
</script>
</body>
</html>
相关推荐
嘟嘟MD4 小时前
程序员副业 | 2025年12月复盘
后端·创业
利刃大大5 小时前
【SpringBoot】Spring事务 && @Transactional详解 && Spring事务失效问题
spring boot·spring·事务
..过云雨6 小时前
17-2.【Linux系统编程】线程同步详解 - 条件变量的理解及应用
linux·c++·人工智能·后端
南山乐只6 小时前
【Spring AI 开发指南】ChatClient 基础、原理与实战案例
人工智能·后端·spring ai
㳺三才人子7 小时前
初探 Spring Framework OncePerRequestFilter
spring boot·spring·junit
这是程序猿7 小时前
基于java的ssm框架学生作业管理系统
java·开发语言·spring boot·spring·学生作业管理系统
努力的小雨8 小时前
从“Agent 元年”到 AI IDE 元年——2025 我与 Vibe Coding 的那些事儿
后端·程序员
几道之旅8 小时前
websocket.WebSocketApp是全双工的吗?
网络·websocket·网络协议
源码获取_wx:Fegn08958 小时前
基于springboot + vue小区人脸识别门禁系统
java·开发语言·vue.js·spring boot·后端·spring
wuxuanok8 小时前
Go——Swagger API文档访问500
开发语言·后端·golang