流式输出技术是一种能够实现数据逐步传输和实时渲染的技术,它在服务器端和客户端都有相应的实现方法。以下是流式输出技术的具体实现方式:
服务器端实现
-
使用SSEEmitter:在Spring Boot中,可以使用
SseEmitter
对象来实现流式输出。通过创建SseEmitter
对象,设置超时时间,然后在新线程中循环发送数据,每次发送数据时调用emitter.send()
方法。当所有数据发送完毕后,调用emitter.complete()
方法完成流式输出。如果发生异常,可以调用emitter.completeWithError()
方法。 -
使用WebFlux:WebFlux是Spring框架中的响应式编程模型,支持非阻塞式I/O操作和事件驱动的编程模式。通过引入Spring WebFlux依赖,可以使用响应式编程的方式实现流式输出。在控制器中,可以返回一个
Flux
或Mono
类型的对象,该对象会逐步生成和发送数据。
客户端实现
-
使用Fetch API:Fetch API提供了一种简单的方式来获取资源,它支持流式处理。通过调用
fetch()
方法获取响应对象,然后使用response.body.getReader()
获取可读流。接着,通过循环读取流中的数据块,直到读取完成。每次读取到数据块时,可以将其解码并更新到页面上。 -
使用SSE(Server-Sent Events):SSE是一种服务器向客户端推送实时更新的技术。在客户端,可以创建一个
EventSource
对象,指定服务器端的流式数据源URL。然后,通过监听onmessage
事件来接收服务器发送的数据,并将其更新到页面上。同时,还可以监听onerror
事件来处理错误情况。
代码示例
-
服务器端SSEEmitter示例:
@RestController public class StreamController { @GetMapping(value = "/stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE) public SseEmitter streamData() { SseEmitter emitter = new SseEmitter(60_000L); new Thread(() -> { try { for (int i = 1; i <= 5; i++) { Thread.sleep(1000); emitter.send("time=" + System.currentTimeMillis()); } emitter.complete(); } catch (Exception e) { emitter.completeWithError(e); } }).start(); return emitter; } }
-
客户端Fetch API示例:
async function fetchStream(url) { const response = await fetch(url); const reader = response.body.getReader(); const decoder = new TextDecoder(); while (true) { const { done, value } = await reader.read(); if (done) break; const chunk = decoder.decode(value); document.getElementById('output').innerHTML += chunk; window.scrollTo(0, document.body.scrollHeight); } }
-
客户端SSE示例:
const eventSource = new EventSource('/stream'); eventSource.onmessage = (event) => { const data = JSON.parse(event.data); appendToDOM(data.content); }; eventSource.onerror = () => { console.error('Stream closed'); };
通过以上方法,可以实现流式输出技术,使得数据能够逐步传输和实时渲染,从而提升用户体验和系统性能。