Skip to content

ResponseBodyEmitter 使用指南

SpringJava

📖 前言

最近在学习 AI Agent 开发,在前后端数据交互的时候遇到这样一个问题:如果使用者向 AI 发送一段提示词,AI 通常的处理完毕的耗时会比较长,因为他是流式输出的,这时候,前端只能静悄悄的等待,给使用者带来的体验就不是很美妙。毕竟,在你讲完话之后,对面静悄悄的,跟死了一样,肯定不是很美妙了,我们需要相对应的流式交互方式来解决这一点,后端的 AI 产生一点内容就向前端输出一点内容,这样就比较美妙了。


🎯 解决问题

适合耗时比较长的任务或者是会持续输出内容的任务,比如下载进度、实时日志、大数据量分片加载等等。

ResponseBodyEmitter:是 Spring MVC(从 4.2 版本引入)提供的一个工具,用于异步、分段地向客户端发送数据

特点:

  • 不阻塞服务器线程:在数据准备好之前,释放容器线程去处理其他请求
  • 流式输出:数据产生一点,就发给客户端一点

非常美妙...


💡 简单示例

java
@GetMapping("/stream")
public ResponseBodyEmitter handle() {
    // 1. 创建一个发射器(可以设置超时时间)
    ResponseBodyEmitter emitter = new ResponseBodyEmitter();

    // 2. 启动异步线程发送数据
    Executors.newSingleThreadExecutor().execute(() -> {
        try {
            for (int i = 0; i < 5; i++) {
                // 模拟耗时操作
                Thread.sleep(1000); 
                // 发送数据
                emitter.send("第 " + i + " 批数据包\n");
            }
            // 3. 全部发送完成
            emitter.complete();
        } catch (Exception e) {
            emitter.completeWithError(e);
        }
    });

    return emitter;
}

可以看出,我们可以直接返回 ResponseBodyEmitter 对象,然后,接受者和发送者之间像是建立了一个管道一样,我们可以让另外一个线程使用创建好的这个对象可以发送数据,另一端会逐步的接收数据,直到通道关闭。


📚 基本用法

文档详见: ResponseBodyEmitter (Spring Framework 7.0.3 API)

构造方法

  • ResponseBodyEmitter() - 常用
  • ResponseBodyEmitter(Long timeout) - 设置超时时间

常用方法

  • send(Object data) - 向客户端发送数据,可以多次调用
  • complete() - 结束响应流,表示数据发送完毕
  • onTimeout(Runnable callback) - 设置超时回调函数
  • onCompletion(Runnable callback) - 设置完成回调函数

🔧 工作原理

  1. 控制器返回对象:Controller 不再返回普通的 StringResponseEntity,而是直接返回 ResponseBodyEmitter 实例

  2. 句柄持有:Spring 会保持这个 HTTP 连接开启

  3. 异步发送:你可以把这个 emitter 丢给另一个异步线程。那个线程只要调用 emitter.send(data),数据就会被推送到客户端

  4. 完成或超时:调用 emitter.complete() 关闭连接,或者因为超时自动断开


⚠️ 注意事项

  • 资源释放:注意用完就丢掉或者直接设置超时时间,超时就关闭
  • 线程安全send() 方法是线程安全的

🔄 相关工具对比

在 Spring 中,你可能还会看到另外两个长得很像的东西:

工具特点适用场景
ResponseBodyEmitter通用的异步流灵活地发送任何对象,Spring 会用 HttpMessageConverter 转成 JSON 等
SseEmitter继承自上面那位,专门用于 Server-Sent Events (SSE)浏览器端的实时推送(类似单向 WebSocket)
StreamingResponseBody性能更高,直接操作 OutputStream适合发送大文件或纯文本流

👋 总结

ResponseBodyEmitter 是一个非常实用的工具,特别适合需要流式输出的场景。通过异步发送数据,可以大大提升用户体验,避免长时间等待的尴尬。

掰掰~

Contact me: 1943284256@qq.com