企业级Websocket即时通讯系统

企业级即时通讯系统实现总结

项目概述

基于 Vue 3 (JavaScript) + Spring Boot 构建的实时聊天系统,采用 WebSocket (STOMP) 协议实现消息推送。

功能特性

  • 公共频道:所有在线用户可见的广播消息
  • 私人聊天:一对一加密消息通信
  • 在线状态:实时显示用户在线/离线状态
  • 消息提醒:页面后台时标题闪烁提示

核心依赖

前端依赖(package.json)

依赖 版本 用途
vue ^3.5.24 前端框架
element-plus ^2.11.7 UI组件库
pinia ^3.0.4 状态管理
sockjs-client ^1.6.1 WebSocket封装
stompjs 2.3.3 STOMP协议客户端

后端依赖(pom.xml)

依赖 版本 用途
spring-boot-starter-parent 2.3.10.RELEASE Spring Boot父工程
spring-boot-starter-websocket - WebSocket支持
hutool-all 5.8.41 工具库
mybatis-plus-boot-starter 3.5.6 ORM框架
sa-token-spring-boot-starter 1.37.0 权限认证

核心技术实现

1. 前端实现

消息存储结构

javascript 复制代码
const publicMessages = ref([]);    // 公共消息列表
const privateMessages = ref({});   // 私人消息(按用户ID存储)

STOMP 连接

javascript 复制代码
const socket = new SockJS('/stomp');
const stompClient = Stomp.over(socket);
stompClient.connect({'token': token}, (frame) => {
    console.log('STOMP 连接成功');
});

频道订阅

  • 公共频道:/topic/public(广播模式)
  • 私人频道:/user/{userId}/queue/private(点对点)

2. 后端实现

WebSocket 配置

java 复制代码
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
    @Override
    public void configureMessageBroker(MessageBrokerRegistry config) {
        config.enableSimpleBroker("/topic", "/queue", "/user");
        config.setApplicationDestinationPrefixes("/app");
    }

	@Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        registry.addEndpoint("/stomp")// 添加 STOMP 端点
                .setHandshakeHandler(new WebSocketHandshakeHandler())// 设置握手处理程序
                .setAllowedOrigins("*")// 允许所有来源
                .withSockJS();// 开启 SockJS 支持
    }
}

自定义WebSocket握手处理类

用于处理WebSocket连接的握手请求,将用户ID绑定到WebSocket会话中

java 复制代码
@Component
@Slf4j
public class WebSocketHandshakeHandler extends DefaultHandshakeHandler {

    @Override
    protected Principal determineUser(ServerHttpRequest request,
                                      WebSocketHandler wsHandler,
                                      Map<String, Object> attributes) {
        String userId = StpUtil.getLoginIdAsString();
        return new StompPrincipal(userId);
    }
}

ws用户信息封装

java 复制代码
/**
 * ws用户信息封装
 *
 * @author Chen
 * @since 2026-5-9 11:05
 */
public class StompPrincipal implements Principal {
    // 用户ID
    private final String name;


    public StompPrincipal(String name) {
        this.name = name;
    }

    @Override
    public String getName() {
        return name;
    }
}

消息处理

@MessageMapping("/chat/public")类型GetMapping,websocket的请求映射

java 复制代码
//前端调用
const destination = currentChannel.value === 'public'
        ? '/app/chat/public'
        : `/app/chat/private/${selectedUser.value.id}`;
    client.send(destination, {}, JSON.stringify({
          content: newMessage.CONTENT,
          fromUserId: userInfoStore.userId,
          toUserId: selectedUser.value?.id,
          msgType: 'text',
          channelType: currentChannel.value
        }
    ));

@SendTo("/topic/public")注解是将返回结果自动广播到主题:/topic/public;也可以手动广播

java 复制代码
//手动发送消息到指定用户队列
messagingTemplate.convertAndSendToUser(toUserId, "/queue/private", response);
java 复制代码
@MessageMapping("/chat/public")
@SendTo("/topic/public")
public ChatResDTO sendPublicMessage(ChatMessageDTO message) {
    return chatService.processPublicMessage(message);
}

@MessageMapping("/chat/private/{toUserId}")
public void sendPrivateMessage(ChatMessageDTO message) {
    chatService.processPrivateMessage(message, message.getToUserId());
}

消息持久化

  • 公共消息:GROUP_ID = 'public'
  • 私人消息:GROUP_ID = 'private',记录双方用户ID

技术架构

复制代码
┌─────────────────────────────────────────────────┐
│  前端 (Vue 3)                                  │
│  ┌─────────┐  ┌─────────┐  ┌─────────┐        │
│  │ 侧边栏  │  │ 聊天面板 │  │ 输入框  │        │
│  └────┬────┘  └────┬────┘  └────┬────┘        │
└───────┼────────────┼────────────┼─────────────┘
        │ WebSocket  │            │
        ▼            ▼            ▼
┌─────────────────────────────────────────────────┐
│  后端 (Spring Boot)                            │
│  ChatController → ChatService → STOMP Broker   │
└───────────────────────────────┬───────────────┘
                               │ JDBC
                               ▼
┌─────────────────────────────────────────────────┐
│  数据库 (MySQL)                                │
│            CHAT_MESSAGE 表                     │
└─────────────────────────────────────────────────┘

技术栈

分类 技术
前端 Vue 3、Pinia、Element Plus
通信 SockJS、STOMP
后端 Spring Boot
数据库 MySQL、Hutool DB

总结

本系统实现了企业级即时通讯的核心功能:

  1. 实时通信:基于 STOMP 协议的毫秒级消息推送
  2. 双频道模式:公共广播 + 私人聊天
  3. 在线状态:实时同步在线用户列表
  4. 消息持久化:所有消息记录到数据库
  5. 用户体验:未读计数、后台提醒等功能

代码结构清晰,易于扩展文件传输、表情等高级功能。

相关推荐
CSharp精选营2 天前
WebSocket 快速入门教程(附示例源码)
websocket·教程·csharp·实时通信·asp.net-core
七夜zippoe15 天前
DolphinDB WebSocket接入:实时数据流
网络·websocket·网络协议·dolphindb·实时数据流
于先生吖15 天前
从零搭建Java萌宠社交系统:WebSocket实时聊天+动态发布模块实现
java·开发语言·websocket
Zhan86112416 天前
WebSocket心跳与断线重连实战:芬兰赫尔辛基指数行情数据接口接入记录
网络·websocket·网络协议
colofullove17 天前
实时游玩页与 WebSocket 状态管理实现
websocket·网络协议·状态模式
小短腿的代码世界17 天前
WebSocket协议在Qt中的工业级实现:5层架构设计与万级并发压测验证
qt·websocket·网络协议
葡萄皮sandy17 天前
SSE和WebSocket
网络·websocket·网络协议
hrw_embedded17 天前
国外新能源充电平台调试OCPP调试平台SteVe和Monta其实是互补的-websoket连接部分。
websocket·ocpp·新能源充电平台·steve·monta
JouYY17 天前
如何实现基于 WebSocket Agent 的断线重连与状态恢复
websocket·llm·agent
BlockWay18 天前
WEEX WebSocket 与 API 生态,正在解决什么问题?
网络·websocket·网络协议