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>
相关推荐
柯南二号1 小时前
【Java后端】Spring Boot 集成 MyBatis-Plus 全攻略
java·spring boot·mybatis
程序员爱钓鱼2 小时前
Go语言实战案例-创建模型并自动迁移
后端·google·go
javachen__2 小时前
SpringBoot整合P6Spy实现全链路SQL监控
spring boot·后端·sql
uzong7 小时前
技术故障复盘模版
后端
GetcharZp8 小时前
基于 Dify + 通义千问的多模态大模型 搭建发票识别 Agent
后端·llm·agent
桦说编程8 小时前
Java 中如何创建不可变类型
java·后端·函数式编程
IT毕设实战小研8 小时前
基于Spring Boot 4s店车辆管理系统 租车管理系统 停车位管理系统 智慧车辆管理系统
java·开发语言·spring boot·后端·spring·毕业设计·课程设计
wyiyiyi9 小时前
【Web后端】Django、flask及其场景——以构建系统原型为例
前端·数据库·后端·python·django·flask
一只爱撸猫的程序猿9 小时前
使用Spring AI配合MCP(Model Context Protocol)构建一个"智能代码审查助手"
spring boot·aigc·ai编程
甄超锋9 小时前
Java ArrayList的介绍及用法
java·windows·spring boot·python·spring·spring cloud·tomcat