极致流式推送!SpringBoot + ResponseBodyEmitter 让异步更丝滑

开发 前端
ResponseBodyEmitter​ 是 Spring 提供的一种 轻量级流式传输解决方案,非常适用于 高并发、实时数据推送 需求。无论是 进度条实时更新、实时聊天、股票数据推送、系统日志流式输出,它都能提供更丝滑的用户体验。

随着 ChatGPT 的兴起,流式输出技术逐渐走进大众视野。在技术社区中,很多开发者开始研究和实践 SSE(服务器推送事件)。不过,SSE 仍然存在一定的局限性,而 Spring 提供的 ResponseBodyEmitter 则是一种更简便的异步流式输出方式。虽然 ResponseBodyEmitter 并非新技术,它早在 Spring Framework 4.2 版本就已经引入,但在实际开发中仍然具有极高的实用价值,特别是在处理实时数据推送时。

ResponseBodyEmitter 的作用

ResponseBodyEmitter 主要用于异步 HTTP 响应处理,其核心优势在于 支持逐步向客户端发送数据,而不是一次性返回所有内容。这种特性特别适用于流式传输或需要长时间处理的任务,例如:

  • 长轮询服务器保持连接开放,待有数据时立即返回。
  • 服务器推送事件(SSE)持续向客户端推送更新信息。
  • 流式传输逐步推送大量数据,如文件下载或实时数据流。
  • 异步处理在后台执行耗时任务,并实时返回处理结果。

典型应用场景

在实际业务中,ResponseBodyEmitter 可广泛应用于:

  • 实时进度更新(例如文件上传进度条)
  • 实时聊天
  • 股票价格推送
  • AI 实时响应
  • 服务器日志流式输出

实战:构建实时日志流

假设我们需要实现一个实时日志查看功能,服务器可以不断地向客户端推送最新的日志信息。

创建控制器

首先,在 Spring Boot 3.4 应用中创建 LogController,使用 ResponseBodyEmitter 处理流式日志输出。

package com.icoderoad.controller;

importorg.springframework.http.MediaType;
importorg.springframework.web.bind.annotation.GetMapping;
importorg.springframework.web.bind.annotation.RequestMapping;
importorg.springframework.web.bind.annotation.RestController;
importorg.springframework.web.servlet.mvc.method.annotation.ResponseBodyEmitter;

@RestController
@RequestMapping("/api/log")
publicclassLogController{
    
    @GetMapping(value ="/stream", produces =MediaType.TEXT_EVENT_STREAM_VALUE)
    publicResponseBodyEmitterstreamLogs(){
        ResponseBodyEmitter emitter =newResponseBodyEmitter();
        
        newThread(()->{
            try{
                while(true){
                    String logEntry =getLatestLogEntry();
                    if(logEntry !=null){
                        emitter.send(logEntry);
                    }
                    Thread.sleep(1000);// 每秒推送一次
                }
            }catch(Exception e){
                emitter.completeWithError(e);
            }
        }).start();
        
        return emitter;
    }
    
    privateStringgetLatestLogEntry(){
        return"2025-02-12 12:00:00 - INFO: 用户成功登录。";
    }
}

运行效果:

访问 http://localhost:8080/api/log/stream,服务器将每秒推送一条新的日志条目,前端可以实时接收并展示。

ResponseBodyEmitter 的核心方法

  • send(Object data)逐步向客户端发送数据,可多次调用。
  • complete()结束响应流。
  • onTimeout(Runnable callback)连接超时时触发回调。
  • onCompletion(Runnable callback)数据发送完成后触发回调。

ResponseBodyEmitter 的工作原理

异步数据生成与推送

在传统 HTTP 响应模式中,服务器通常需要等待整个响应数据生成完成后再返回。而 ResponseBodyEmitter 允许 异步逐步推送数据,即部分数据准备好后立即 send() 给客户端,提高响应速度。

分块传输(Chunked Encoding)

传统 HTTP 响应头需要指定 Content-Length,但 ResponseBodyEmitter 采用 分块传输(Chunked Encoding),无需指定数据总长度,而是将数据分块推送,客户端收到后即可立即处理,减少等待时间。

连接生命周期管理

  • 数据发送完毕时调用 complete() 关闭连接,避免资源浪费。
  • 若发生异常,调用 completeWithError(),通知客户端连接关闭。

注意事项

  • 客户端支持:大多数现代浏览器和 HTTP 客户端都支持 ResponseBodyEmitter,但部分旧版本可能存在兼容性问题。
  • 超时管理:建议设置超时时间,避免长连接占用资源,例如:
emitter.onTimeout(() -> emitter.complete());
  • 线程安全:send() 方法是线程安全的,但仍需合理管理任务线程,避免资源泄漏。
  • 连接关闭:务必调用 complete() 或 completeWithError() 以释放资源。

ResponseBodyEmitter 与其他流式技术对比

技术方案

适用场景

优缺点

Streaming

低级字节流传输

灵活性高,但需要手动管理 OutputStream关闭

SSE

服务器推送事件

需浏览器支持 text/event-stream 协议

ResponseBodyEmitter

通用 HTTP 流式传输

兼容性更好,易于与 Spring 集成

在 AI 流式输出等场景下,ResponseBodyEmitter 相比 SSE 具有更好的 HTTP 兼容性,且使用方式更灵活。

结语

ResponseBodyEmitter 是 Spring 提供的一种轻量级流式传输解决方案,非常适用于 高并发、实时数据推送 需求。无论是 进度条实时更新、实时聊天、股票数据推送、系统日志流式输出,它都能提供更丝滑的用户体验。如果你的应用需要高效的异步数据推送,不妨试试 ResponseBodyEmitter 吧!

责任编辑:武晓燕 来源: 路条编程
相关推荐

2025-03-10 00:00:11

Spring框架数据

2025-03-03 12:00:00

JavaScriptfor 循环语言

2020-07-22 15:15:28

Vue前端代码

2023-09-27 07:49:23

2023-03-15 15:54:36

Java代码

2022-08-28 10:08:53

前端代码前端

2021-11-17 08:16:03

内存控制Go

2021-07-14 13:46:28

KubeVela阿里云容器

2023-07-06 08:10:57

Vue3参数请求

2024-07-25 09:40:00

2023-09-13 16:34:47

Java工具开发

2024-05-30 11:44:37

2023-06-26 08:01:42

debugger技巧代码

2021-01-18 18:42:33

工具调优开发

2022-03-18 13:59:46

缓存RedisCaffeine

2022-08-16 08:37:09

视频插帧深度学习

2014-01-21 14:19:30

多看阅读移动阅读

2023-03-03 17:00:00

部署Linux内核

2024-05-21 10:28:51

API设计架构

2019-05-16 09:07:42

华为方舟编译器
点赞
收藏

51CTO技术栈公众号