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>
相关推荐
MadPrinter1 小时前
SpringBoot学习日记 Day11:博客系统核心功能深度开发
java·spring boot·后端·学习·spring·mybatis
dasseinzumtode1 小时前
nestJS 使用ExcelJS 实现数据的excel导出功能
前端·后端·node.js
淦出一番成就1 小时前
Java反序列化接收多种格式日期-JsonDeserialize
java·后端
Java中文社群1 小时前
Hutool被卖半年多了,现状是逆袭还是沉寂?
java·后端
程序员蜗牛2 小时前
9个Spring Boot参数验证高阶技巧,第8,9个代码量直接减半!
后端
yeyong2 小时前
咨询kimi关于设计日志告警功能,还是有启发的
后端
库森学长2 小时前
2025年,你不能错过Spring AI,那个汲取了LangChain灵感的家伙!
后端·openai·ai编程
Java水解2 小时前
Spring Boot 启动流程详解
spring boot·后端
学历真的很重要2 小时前
Claude Code Windows 原生版安装指南
人工智能·windows·后端·语言模型·面试·go
转转技术团队2 小时前
让AI成为你的编程助手:如何高效使用Cursor
后端·cursor