当前位置: 首页 > 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.lryc.cn/news/582635.html

相关文章:

  • springboot单体项目的发布生产优化
  • 【保姆级目标检测教程】Ubuntu 20.04 部署 YOLOv13 全流程(附训练/推理代码)
  • 基于SpringBoot+Vue的非遗文化传承管理系统(websocket即时通讯、协同过滤算法、支付宝沙盒支付、可分享链接、功能量非常大)
  • 【WEB】Polar靶场 16-20题 详细笔记
  • 从0到1搭建ELK日志收集平台
  • OpenCV探索之旅:形态学魔法
  • mit6.5840-lab3-3D-SnapShot-25Summer
  • nmon使用方法
  • 人工智能大模型(LLM)论文17道菜
  • Python3完全新手小白的学习手册 12代码测试
  • 7 种简单方法将三星文件传输到电脑
  • go入门 - day1 - 环境搭建
  • MATLAB 实现 SRCNN 图像超分辨率重建
  • Go与JS无缝协作:Goja引擎实战之错误处理最佳实践
  • 深度学习-多分类
  • 二分查找篇——搜索二维矩阵【LeetCode】遍历法
  • Mysql常用内置函数,复合查询及内外连接
  • 嘉立创黄山派下载watch ui demo 教程(sf32)
  • (电机03)分享FOC控制中SVPWM的输出关联硬件
  • [ESP32]VSCODE+ESP-IDF环境搭建及blink例程尝试(win10 win11均配置成功)
  • Sa-Token完全学习指南
  • npm 包 scheduler 介绍
  • C++STL-vector
  • 股票数据源对接技术指南:印度尼西亚、印度、韩国
  • 静态路由实验以及核心原理
  • ubuntu24.04安装NFS网络文件系统/ARM开发板NFS挂载
  • 香港风水(原生)林地的逻辑分类器
  • 香港站群服务器价格怎么样?
  • Android UI 组件系列(四):EditText 使用详解与输入限制
  • LabVIEW-GPRS 远程土壤监测