Java 返回流式数据给前端,常用于以下场景:

  • 🔁 实时反馈处理进度或响应内容(如 AI 聊天、日志、下载进度);
  • ✅ SSE(Server-Sent Events);
  • ✅ 响应式流(WebFlux);
  • ✅ OutputStream/StreamingResponseBody(用于大文件或数据分块);

✅ 常见方式汇总

技术用途/场景说明
SseEmitter基于 Spring MVC 的服务端推送推送事件 text/event-stream 格式
Flux<String>Spring WebFlux 的响应式数据流非阻塞,适合 reactive 应用
StreamingResponseBody流式文件输出或纯文本输出适合文件下载/导出等大数据量
OutputStreamServlet 原生流输出自定义写入控制
WebSocket双向通信,实时性强用于聊天、游戏、AI 等互动

示例 1:SseEmitter 返回流式数据(Spring Boot MVC)

@GetMapping("/sse")
public SseEmitter stream() {
    SseEmitter emitter = new SseEmitter(0L); // 0L 表示无限超时

    new Thread(() -> {
        try {
            for (int i = 0; i < 5; i++) {
                emitter.send(SseEmitter.event().data("第 " + i + " 条消息"));
                Thread.sleep(1000);
            }
            emitter.complete();
        } catch (IOException | InterruptedException e) {
            emitter.completeWithError(e);
        }
    }).start();

    return emitter;
}

前端代码(原生 JS):

<script>
  const source = new EventSource("/sse");
  source.onmessage = e => {
    console.log("收到数据:", e.data);
  };
</script>

示例 2:WebFlux 的 Flux<String> 输出

@GetMapping(value = "/flux", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<String> fluxStream() {
    return Flux.interval(Duration.ofMillis(500))
               .map(i -> "消息: " + i)
               .take(10);
}

适用于 Spring WebFlux 项目(需要依赖 spring-boot-starter-webflux)。


示例 3:StreamingResponseBody 返回文本流或文件下载

@GetMapping("/stream-text")
public ResponseEntity<StreamingResponseBody> streamText() {
    StreamingResponseBody stream = outputStream -> {
        for (int i = 0; i < 5; i++) {
            outputStream.write(("行:" + i + "\n").getBytes());
            outputStream.flush();
            Thread.sleep(500);
        }
    };

    return ResponseEntity.ok()
            .contentType(MediaType.TEXT_PLAIN)
            .body(stream);
}

适合返回大型纯文本数据(如日志、CSV 等)。


示例 4:Servlet 原生方式(低层控制)

@GetMapping("/native")
public void nativeStream(HttpServletResponse response) throws IOException {
    response.setContentType("text/plain;charset=UTF-8");
    ServletOutputStream out = response.getOutputStream();

    for (int i = 0; i < 5; i++) {
        out.write(("line " + i + "\n").getBytes());
        out.flush();
        try {
            Thread.sleep(1000);
        } catch (InterruptedException ignored) {}
    }
    out.close();
}

示例 5:与 OpenAI 接口结合(SSE流式响应)

我们已在前文 Canvas 中构建了:

/api/chat-stream       // Flux
/api/chat-sse          // SseEmitter

总结

场景推荐方式
浏览器端单向推送(如 AI 回答)SseEmitter / Flux<String>
文件/日志下载(分块)StreamingResponseBody
原生控制高/兼容老系统OutputStream
聊天/双向实时通信WebSocket