当前位置: 首页 > news >正文

【Spring WebSocket详解】Spring WebSocket从入门到实战

一、WebSocket协议基础

        1.1 Websocket概念

        1.2 WebSocket握手流程:

二、Spring WebSocket技术详解

        2.1 Spring WebSocket概述

        2.2 STOMP协议支持

三、 STOMP协议实现简单通信系统

        3.1 pom.xml文件

        3.2 配置STOMP代理

        3.3 使用@MessageMapping的Controller

        3.4 前端连接STOMP(Vue2)

四、Spring WebSocket构建简单实时通信系统

        4.1 pom.xml文件

        4.2 核心配置类

        4.3 消息处理器类

        4.4 客户端测试代码(Vue2)

五、扩展与其他


在现代Web应用中,实时通信已成为基本需求。无论是聊天应用、实时通知系统还是在线协作工具,都需要服务器能够主动向客户端推送消息。本文将详细介绍如何使用Spring WebSocket构建一个高效的实时通信系统。

一、WebSocket协议基础

1.1 Websocket概念

WebSocket是一种在单个TCP连接上进行全双工通信的协议,解决了HTTP协议的半双工和轮询效率低的问题。其核心特点:

全双工:客户端和服务端可同时发送数据。

持久连接:一次握手后保持长连接。

低延迟:无需频繁建立连接。

1.2 WebSocket握手流程:

客户端发起HTTP请求:包含Upgrade:websocket头。

服务端响应101状态码:表示协议切换成功。

数据帧传输:后续通信通过二进制帧(Frame)进行。

握手请求示例

GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
Sec-WebSocket-Version: 13

握手响应示例

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消息的接口

public class MyRawHandler implements WebSocketHandler {// 处理消息@Overridepublic 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连接

// 广播消息到主题
template.convertAndSend("/topic/public", chatMessage);// 发送给特定用户
template.convertAndSendToUser(userId, "/queue/private", message);

SimpMessagingTemplate:用于发送消息的工具类

// 广播消息到主题
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:用户专属队列(自动转换)

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

订阅/发布模式:

前端订阅:

stompClient.subscribe('/topic/public', (message) => {console.log('收到广播:', message.body);
});stompClient.subscribe('/user/queue/private', (message) => {console.log('收到私信:', message.body);
});

后端发布:

@MessageMapping("/chat")
@SendTo("/topic/public") 
public ChatMessage broadcast(ChatMessage message) {return message; // 自动发送到/topic/public
}

消息确认ACK机制:

服务端配置:

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {@Overridepublic void configureClientInboundChannel(ChannelRegistration registration) {registration.interceptors(new ChannelInterceptor() {@Overridepublic Message<?> preSend(Message<?> message, MessageChannel channel) {// 消息到达前的处理return message;}});}
}

客户端ACK示例:

stompClient.subscribe('/topic/orders', (message) => {processOrder(message.body);message.acknowledge(); // 显式确认
}, { 'ack': 'client' });

三、 STOMP协议实现简单通信系统

3.1 pom.xml文件

<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId><version>2.7.0</version></dependency>
</dependencies>

3.2 配置STOMP代理

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketStompConfig implements WebSocketMessageBrokerConfigurer {@Overridepublic void configureMessageBroker(MessageBrokerRegistry registry) {registry.enableSimpleBroker("/topic"); // 客户端订阅前缀registry.setApplicationDestinationPrefixes("/app"); // 服务端接收前缀}@Overridepublic void registerStompEndpoints(StompEndpointRegistry registry) {registry.addEndpoint("/ws-stomp").withSockJS(); // 连接端点}
}

 3.3 使用@MessageMapping的Controller

@Controller
public class StompMessageController {// 处理发送到 "/app/chat" 的消息@MessageMapping("/chat")  @SendTo("/topic/messages") // 自动广播到所有订阅"/topic/messages"的客户端public String handleChat(String message) {return "回复: " + message;}
}

3.4 前端连接STOMP(Vue2)

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文件

<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId><version>2.7.0</version></dependency>
</dependencies>

4.2 核心配置类

/*** WebSocket 配置类,用于配置 WebSocket 相关参数和处理器*/
@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {@Autowired  // 自动注入自定义的 WebSocket 消息处理器private BroadcastWebSocketHandler handler;@Overridepublic void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {// 添加自定义的 WebSocket 处理器,并指定 WebSocket 连接路径registry.addHandler(handler, "/ws")// 设置允许跨域访问,* 表示允许所有来源.setAllowedOrigins("*");// 可以继续添加其他配置,例如:// .withSockJS()  // 如果需要支持 SockJS 可以添加此项}
}

4.3 消息处理器类

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. 连接建立时触发@Overridepublic void afterConnectionEstablished(WebSocketSession session) {sessions.add(session);log.info("新连接: ID={}, URI={}", session.getId(), session.getUri());}// 2. 接收文本消息时触发@Overrideprotected 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. 连接关闭时触发@Overridepublic void afterConnectionClosed(WebSocketSession session, CloseStatus status) {sessions.remove(session);log.info("连接关闭: ID={}, 原因={}", session.getId(), status.getReason());}// 4. 传输错误处理@Overridepublic void handleTransportError(WebSocketSession session, Throwable exception) {log.error("传输错误: " + session.getId(), exception);}
}

4.4 前端连接代码(Vue2)

// 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实时通信系统,满足大多数实时通信场景的需求,如果有其他问题欢迎评论区留言讨论。

http://www.dtcms.com/a/269836.html

相关文章:

  • Spring Boot 事务失效问题:同一个 Service 类中方法调用导致事务失效的原因及解决方案
  • MATLAB/Simulink电机控制仿真代做 同步异步永磁直驱磁阻双馈无刷
  • CD46.【C++ Dev】list的模拟实现(1)
  • 一天一道Sql题(day02)
  • SSH密钥 与 Ed25519密钥 是什么关系
  • 服务器的RAID存储方案如何选择最合适?
  • 20250708-2-Kubernetes 集群部署、配置和验证-使用kubeadm快速部署一个K8s集群_笔记
  • 兰顿蚂蚁路径lua测试
  • 无缝高清矩阵与画面分割器的区别
  • OpenWebUI(5)源码学习-后端socket通信模块
  • Apache DolphinScheduler保姆级实操指南:云原生任务调度实战
  • iOS打包流程
  • navicat导出数据库的表结构
  • 鸿蒙分布式开发实战指南:让设备协同像操作本地一样简单
  • 深度 |以数字技术赋能服务消费场景创新
  • kafka如何让消息均匀的写入到每个partition
  • Spring Boot 多数据源切换:AbstractRoutingDataSource
  • Elasticsearch Kibana 使用 原理
  • 用基础模型构建应用(第七章)AI Engineering: Building Applications with Foundation Models学习笔记
  • Linux基础篇、第五章_01利用 Cobbler 实现 CentOS 7 与 Rocky 9.5 自动化安装全攻略
  • 记录一次在 centos 虚拟机 中 安装 Java环境
  • windows内核研究(系统调用 1)
  • 从传统项目管理到敏捷DevOps:如何转向使用DevOps看板工具进行工作流管理
  • 谁主沉浮:人工智能对未来信息技术发展路径的影响研究
  • 优化提示词提升VLLM准确率
  • K8s——配置管理(1)
  • 构建高效分布式系统:bRPC组合Channels与HTTP/H2访问指南
  • 从单体到微服务:Spring Cloud 开篇与微服务设计
  • 微前端框架对比
  • 无缝矩阵支持音频分离带画面分割功能的全面解析