[1.1 Websocket概念](#1.1 Websocket概念)
[1.2 WebSocket握手流程:](#1.2 WebSocket握手流程:)
[二、Spring WebSocket技术详解](#二、Spring WebSocket技术详解)
[2.1 Spring WebSocket概述](#2.1 Spring WebSocket概述)
[2.2 STOMP协议支持](#2.2 STOMP协议支持)
[三、 STOMP协议实现简单通信系统](#三、 STOMP协议实现简单通信系统)
[3.1 pom.xml文件](#3.1 pom.xml文件)
[3.2 配置STOMP代理](#3.2 配置STOMP代理)
[3.3 使用@MessageMapping的Controller](#3.3 使用@MessageMapping的Controller)
[3.4 前端连接STOMP(Vue2)](#3.4 前端连接STOMP(Vue2))
[四、Spring WebSocket构建简单实时通信系统](#四、Spring WebSocket构建简单实时通信系统)
[4.1 pom.xml文件](#4.1 pom.xml文件)
[4.2 核心配置类](#4.2 核心配置类)
[4.3 消息处理器类](#4.3 消息处理器类)
[4.4 客户端测试代码(Vue2)](#4.4 客户端测试代码(Vue2))
在现代Web应用中,实时通信已成为基本需求。无论是聊天应用、实时通知系统还是在线协作工具,都需要服务器能够主动向客户端推送消息。本文将详细介绍如何使用Spring WebSocket构建一个高效的实时通信系统。
一、WebSocket协议基础
1.1 Websocket概念
WebSocket是一种在单个TCP连接上进行全双工通信的协议,解决了HTTP协议的半双工和轮询效率低的问题。其核心特点:
全双工:客户端和服务端可同时发送数据。
持久连接:一次握手后保持长连接。
低延迟:无需频繁建立连接。
1.2 WebSocket握手流程:
客户端发起HTTP请求:包含Upgrade:websocket头。
服务端响应101状态码:表示协议切换成功。
数据帧传输:后续通信通过二进制帧(Frame)进行。
握手请求示例:
html
GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
Sec-WebSocket-Version: 13
握手响应示例:
html
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=
二、Spring WebSocket技术详解
2.1 Spring WebSocket概述
Spring WebSocket是Spring框架对WebSocket协议的实现,提供了更高层次的抽象,与Spring生态系统无缝集成。

核心组件:
WebSocketHandler:处理WebSocket消息的接口
java
public class MyRawHandler implements WebSocketHandler {
// 处理消息
@Override
public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) {
if (message instanceof TextMessage) {
handleTextMessage(session, (TextMessage) message);
}
else if (message instanceof BinaryMessage) {
handleBinaryMessage(session, (BinaryMessage) message);
}
}
// 必须实现的空方法(适配器模式)
@Override public void afterConnectionEstablished(WebSocketSession session) {}
@Override public void handleTransportError(WebSocketSession session, Throwable exception) {}
@Override public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) {}
@Override public boolean supportsPartialMessages() { return false; }
}
WebSocketSession:代表一个WebSocket连接
java
// 广播消息到主题
template.convertAndSend("/topic/public", chatMessage);
// 发送给特定用户
template.convertAndSendToUser(userId, "/queue/private", message);
SimpMessagingTemplate:用于发送消息的工具类
java
// 广播消息到主题
template.convertAndSend("/topic/public", chatMessage);
// 发送给特定用户
template.convertAndSendToUser(userId, "/queue/private", message);
@MessageMapping:是 Spring STOMP协议的一部分,用于定义消息的接收端点(类似HTTP的 @RequestMapping)
2.2 STOMP协议支持

Spring WebSocket默认支持STOMP(Simple Text Oriented Messaging Protocol)子协议,提供了更高级的消息模式:
目的地(Destination)概念:
/app:应用前缀(由@MessageMapping处理)
/topic:广播目的地
/queue:点对点队列
/user:用户专属队列(自动转换)
java
@Override
public void configureMessageBroker(MessageBrokerRegistry config) {
config.setApplicationDestinationPrefixes("/app");
config.enableSimpleBroker("/topic", "/queue");
config.setUserDestinationPrefix("/user");
}
订阅/发布模式:
前端订阅:
javascript
stompClient.subscribe('/topic/public', (message) => {
console.log('收到广播:', message.body);
});
stompClient.subscribe('/user/queue/private', (message) => {
console.log('收到私信:', message.body);
});
后端发布:
java
@MessageMapping("/chat")
@SendTo("/topic/public")
public ChatMessage broadcast(ChatMessage message) {
return message; // 自动发送到/topic/public
}
消息确认ACK机制:
服务端配置:
java
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
@Override
public void configureClientInboundChannel(ChannelRegistration registration) {
registration.interceptors(new ChannelInterceptor() {
@Override
public Message<?> preSend(Message<?> message, MessageChannel channel) {
// 消息到达前的处理
return message;
}
});
}
}
客户端ACK示例:
javascript
stompClient.subscribe('/topic/orders', (message) => {
processOrder(message.body);
message.acknowledge(); // 显式确认
}, { 'ack': 'client' });
三、 STOMP协议实现简单通信系统
3.1 pom.xml文件
XML
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
<version>2.7.0</version>
</dependency>
</dependencies>
3.2 配置STOMP代理
java
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketStompConfig implements WebSocketMessageBrokerConfigurer {
@Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
registry.enableSimpleBroker("/topic"); // 客户端订阅前缀
registry.setApplicationDestinationPrefixes("/app"); // 服务端接收前缀
}
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/ws-stomp").withSockJS(); // 连接端点
}
}
3.3 使用@MessageMapping的Controller
java
@Controller
public class StompMessageController {
// 处理发送到 "/app/chat" 的消息
@MessageMapping("/chat")
@SendTo("/topic/messages") // 自动广播到所有订阅"/topic/messages"的客户端
public String handleChat(String message) {
return "回复: " + message;
}
}
3.4 前端连接STOMP(Vue2)
javascript
const socket = new SockJS('/ws-stomp');
const stompClient = Stomp.over(socket);
stompClient.connect({}, () => {
// 订阅消息
stompClient.subscribe('/topic/messages', (response) => {
console.log("收到广播: " + response.body);
});
// 发送消息
stompClient.send("/app/chat", {}, "Hello STOMP!");
});
四、Spring WebSocket构建简单实时通信系统
4.1 pom.xml文件
XML
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
<version>2.7.0</version>
</dependency>
</dependencies>
4.2 核心配置类
java
/**
* WebSocket 配置类,用于配置 WebSocket 相关参数和处理器
*/
@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {
@Autowired // 自动注入自定义的 WebSocket 消息处理器
private BroadcastWebSocketHandler handler;
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
// 添加自定义的 WebSocket 处理器,并指定 WebSocket 连接路径
registry.addHandler(handler, "/ws")
// 设置允许跨域访问,* 表示允许所有来源
.setAllowedOrigins("*");
// 可以继续添加其他配置,例如:
// .withSockJS() // 如果需要支持 SockJS 可以添加此项
}
}
4.3 消息处理器类
java
import org.springframework.web.socket.*;
import org.springframework.web.socket.handler.TextWebSocketHandler;
import java.util.concurrent.CopyOnWriteArrayList;
public class CustomWebSocketHandler extends TextWebSocketHandler {
// 线程安全的连接集合
private final List<WebSocketSession> sessions = new CopyOnWriteArrayList<>();
// 1. 连接建立时触发
@Override
public void afterConnectionEstablished(WebSocketSession session) {
sessions.add(session);
log.info("新连接: ID={}, URI={}", session.getId(), session.getUri());
}
// 2. 接收文本消息时触发
@Override
protected void handleTextMessage(WebSocketSession session, TextMessage message) {
String payload = message.getPayload();
log.info("收到消息: 来自{} 内容={}", session.getId(), payload);
// 使用Jackson将JSON字符串转换为User对象(假如是user对象)
ObjectMapper objectMapper = new ObjectMapper();
User user = objectMapper.readValue(payload, User.class);
// 业务处理逻辑
processMessage(session, payload);
}
// 3. 连接关闭时触发
@Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus status) {
sessions.remove(session);
log.info("连接关闭: ID={}, 原因={}", session.getId(), status.getReason());
}
// 4. 传输错误处理
@Override
public void handleTransportError(WebSocketSession session, Throwable exception) {
log.error("传输错误: " + session.getId(), exception);
}
}

4.4 前端连接代码(Vue2)
javascript
// Client1
const ws1 = new WebSocket('ws://localhost:8080/ws');
ws1.onmessage = e => console.log('客户端1收到:', e.data);
ws1.send("Hello from Client1");
// Client2
const ws2 = new WebSocket('ws://localhost:8080/ws');
ws2.onmessage = e => console.log('客户端2收到:', e.data);
ws2.send("Hello from Client2");
五、扩展与其他
如果你希望使用Netty实现性能更好的通信系统,请参考我的其他文章:
通过以上实战指南,您可以通过编写指定的handler类来构建一个稳定、高效、可扩展的Spring WebSocket实时通信系统,满足大多数实时通信场景的需求,如果有其他问题欢迎评论区留言讨论。