Java 返回流式数据给前端,常用于以下场景:
- 🔁 实时反馈处理进度或响应内容(如 AI 聊天、日志、下载进度);
- ✅ SSE(Server-Sent Events);
- ✅ 响应式流(WebFlux);
- ✅ OutputStream/StreamingResponseBody(用于大文件或数据分块);
✅ 常见方式汇总
技术 | 用途/场景 | 说明 |
---|---|---|
SseEmitter | 基于 Spring MVC 的服务端推送 | 推送事件 text/event-stream 格式 |
Flux<String> | Spring WebFlux 的响应式数据流 | 非阻塞,适合 reactive 应用 |
StreamingResponseBody | 流式文件输出或纯文本输出 | 适合文件下载/导出等大数据量 |
OutputStream | Servlet 原生流输出 | 自定义写入控制 |
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 |
发表回复