| 特性 | SSE | 轮询 | WebSocket |
|---|---|---|---|
| 通讯方向 | 服务器向客户端推送数据 | 客户端定时请求服务器获取数据 | 客户端与服务器双向通讯 |
| 连接类型 | 长连接:使用 HTTP/1.1 或 HTTP/2 长连接 | 短连接:每次请求都是独立的 HTTP 请求 | 长连接:通过 TCP 建立的持久连接 |
| 传输协议 | HTTP/1.1 或 HTTP/2 | HTTP | TCP |
| 浏览器支持 | 广泛支持(HTML5 原生支持) | 全面支持,所有浏览器均支持 | 广泛支持(需通过 WebSocket API 实现) |
| 消息发送频率 | 服务器可随时推送数据 | 客户端主动定时请求,频率取决于客户端设置 | 实时、即时双向发送 |
| 服务器开销 | 较低:只需保持一个长连接 | 高:每次请求都需要重新建立 HTTP 连接 | 较高:需保持 TCP 连接,管理心跳包 |
| 客户端开销 | 低:只需处理服务器推送的数据 | 高:每次请求都会产生额外的资源消耗 | 中等:需保持与服务器的连接 |
| 传输数据格式 | 纯文本、JSON 等 | 纯文本、JSON 等 | 任意格式(二进制、文本等) |
| 连接恢复机制 | 自动恢复:连接中断时,客户端会自动重新连接 | 无自动恢复,需客户端重新发起请求 | 需开发者自行实现重连机制 |
| 适用场景 | 适合实时数据推送、通知、监控等单向通讯场景 | 适用于低频率、对实时性要求不高的场景 | 适合即时通讯、协作应用等双向通讯场景 |
| 复杂度 | 简单:实现轻量且代码量少 | 简单:代码量少,但性能较差 | 复杂:需处理更多逻辑,如握手、心跳等 |
| 实时性 | 高:服务器可立即推送消息 | 低:依赖客户端的请求频率 | 高:双向即时通讯 |
| 防火墙/代理兼容性 | 高:使用标准 HTTP 协议,通常无额外配置需求 | 高:使用标准 HTTP 协议 | 可能较低:需配置防火墙或代理来允许 TCP 连接 |
| 带宽消耗 | 较低:保持长连接,但只在有数据时传输 | 较高:每次轮询都会消耗资源和带宽 | 较低:保持长连接,数据按需传输 |
轮询
SSE
WebSocket
xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>方法概念
- WebSocketSession:表示当前 WebSocket 会话,通过它可以访问当前连接的信息,例如会话 ID、客户端信息等
- 如果前端断开了连接,sendMessage 发送消息时,会抛出 IOException
- TextWebSocketHandler
- afterConnectionEstablished 在 WebSocket 连接成功后被调用
- afterConnectionClosed 在 WebSocket 连接关闭后被调用
- handleTransportError 当 WebSocket 连接发生传输错误时被调用
- handleTextMessage 当接收到客户端发送的文本消息时,调用此方法进行处理。可以在这里解析消息、执行操作,并且可以通过 session 对象回复消息给客户端
实战
- 注册访问端点
java
/**
* WebSocket 配置类
*/
@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {
private @Resource ImageProcessingArchivesHandler imageProcessingArchivesHandler;
private @Resource ImageProcessingArchivesFilesHandler imageProcessingArchivesFilesHandler;
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
// 注册 WebSocket 处理器,添加访问路径和可访问的源
registry.addHandler(imageProcessingArchivesHandler, "/imageProcessingArchives").setAllowedOrigins("*");
registry.addHandler(imageProcessingArchivesFilesHandler, "/imageProcessingArchiveFiles").setAllowedOrigins("*");
}
}- 处理器
java
/**
* 图像处理进度 Handler - 案卷级
*/
@Component
@RequiredArgsConstructor
public class ImageProcessingArchivesHandler extends TextWebSocketHandler {
private final ObjectMapper objectMapper;
private final IImageProcessingService imageProcessingService;
private final VolFilesMapper volFilesMapper;
@Override
public void afterConnectionEstablished(WebSocketSession session) {
try {
System.out.println("WebSocket 连接成功!");
} catch (Exception e) {
log.error("WebSocket 错误:" + e.getMessage());
}
}
@Override
public void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
int processedImages = 0;
int totalImages = scannedFiles.size();
while (true) {
if (processedImages > totalImages) {
session.close(CloseStatus.NORMAL); // 关闭 WebSocket 连接
break;
}
ObjectNode objectNode = objectMapper.createObjectNode()
.put("processedImages", processedImages)
.put("totalImages", totalImages);
session.sendMessage(new TextMessage(objectMapper.writeValueAsString(objectNode)));
Thread.sleep(1000); // 每秒发送一次进度
processedImages++;
}
}
}- 前端访问 :ws://localhost:8060/imageProcessingArchives
状态码
- 报错 1006 连接被关闭 : Spring Security 默认会拦截所有请求,包括 WebSocket 的握手请求。因此,需要在 Spring Security 配置中明确允许 WebSocket 请求通过