Java 中实现流式输出(Streaming Output)常见于以下几种应用场景:
- ✅ 与前端配合展示“逐步加载”(如聊天 AI 实时回复);
- ✅ 大文件分块下载;
- ✅ 后端实时日志/进度反馈;
- ✅ SSE(Server-Sent Events)/ WebSocket 流式推送。
✅ 1. 使用 SseEmitter
实现服务端逐步发送(Spring Boot)
@RestController
public class StreamController {
@GetMapping("/stream")
public SseEmitter stream() {
SseEmitter emitter = new SseEmitter(0L); // 不设置超时时间
new Thread(() -> {
try {
for (int i = 1; i <= 10; i++) {
emitter.send("第 " + i + " 条数据");
Thread.sleep(500);
}
emitter.complete();
} catch (Exception e) {
emitter.completeWithError(e);
}
}).start();
return emitter;
}
}
前端监听方式(HTML 示例):
<script>
const source = new EventSource("/stream");
source.onmessage = e => {
console.log("收到数据:", e.data);
};
</script>
✅ 2. 使用 ResponseBodyEmitter
流式输出普通 HTTP 内容
@GetMapping("/text-stream")
public ResponseBodyEmitter streamText() {
ResponseBodyEmitter emitter = new ResponseBodyEmitter();
new Thread(() -> {
try {
for (int i = 0; i < 5; i++) {
emitter.send("行:" + i + "\n", MediaType.TEXT_PLAIN);
Thread.sleep(1000);
}
emitter.complete();
} catch (IOException | InterruptedException e) {
emitter.completeWithError(e);
}
}).start();
return emitter;
}
📌 适用于纯文本输出,不需要
text/event-stream
的场景。
✅ 3. 使用 Flux<String>
(Spring WebFlux)实现响应式流输出
@GetMapping(value = "/flux-stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<String> streamFlux() {
return Flux.interval(Duration.ofMillis(500))
.map(i -> "flux 数据:" + i)
.take(10);
}
📌 WebFlux 和 reactive stack 专用,效果类似于
SseEmitter
。
✅ 4. 控制台或日志流式输出(非 Web)
public class StreamDemo {
public static void main(String[] args) throws InterruptedException {
for (int i = 1; i <= 5; i++) {
System.out.print("第 " + i + " 行\r");
Thread.sleep(500);
}
}
}
📌 控制台实时输出(如进度条),常用于 CLI 工具。
总结:根据场景选方式
场景 | 推荐方式 |
---|---|
后端推送给浏览器 | SseEmitter 或 Flux (SSE) |
控制台实时输出 | System.out.print |
REST 接口返回大文件/大数据 | StreamingResponseBody 或 OutputStream |
与前端聊天/AI 对话联动 | SseEmitter + WebClient |
发表回复