前言
流式响应(如基于 Spring WebFlux 实现的 SSE)依托 Spring WebFlux 框架构建,核心作用是让服务器能实时、分段地向客户端推送数据,而非一次性返回完整结果。
依赖
<!-- Spring WebFlux核心依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
流式响应代码(一句一句返回)
/**
* 流式响应
* 记得加produces = MediaType.TEXT_EVENT_STREAM_VALUE,否则会一起返回
*/
@SneakyThrows
@PostMapping(value = "streamPush", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<Object> streamPush(){
//查询数据
List<String> dataList = new ArrayList<>();
//图片地址
String annotatedImage = "";
return Flux.interval(Duration.ofSeconds(1))
.flatMap(tick -> Flux.create(sink -> this.streamingOutput(sink,dataList,annotatedImage)))
.takeUntil("[COMPLETED]"::equals)
.share()
.publishOn(Schedulers.boundedElastic());
}
/**
* 流式输出核心逻辑:分段推送数据,支持自定义格式
* @param sink 数据流写入端(控制数据推送)
* @param list 业务数据列表
* @param annotatedImage 图片地址
*/
public void streamingOutput(FluxSink<Object> sink, List<String> list, String annotatedImage){
//sink.next就会手动推送数据
sink.next("<incident>");
for (String data : list) {
sink.next(data);
}
sink.next("</incident>");
sink.next("<img>");
sink.next(annotatedImage);
sink.next("</img>");
sink.next("[COMPLETED]");
sink.complete();
}
流式响应效果(一句一句返回)

流式响应代码(逐字返回)
/**
* 流式响应
* 记得加produces = MediaType.TEXT_EVENT_STREAM_VALUE,否则会一起返回
*/
@SneakyThrows
@PostMapping(value = "streamPush", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<Object> streamPush(){
//查询数据
List<String> dataList = new ArrayList<>();
//图片地址
String annotatedImage = "";
return Flux.interval(Duration.ofSeconds(1))
.flatMap(tick -> Flux.create(sink -> this.streamingOutput(sink,dataList,annotatedImage)))
.takeUntil("[COMPLETED]"::equals)
.share()
.publishOn(Schedulers.boundedElastic());
}
/**
* 流式输出核心逻辑:分段推送数据,支持自定义格式
* @param sink 数据流写入端(控制数据推送)
* @param list 业务数据列表
* @param annotatedImage 图片地址
*/
public void streamingOutput(FluxSink<Object> sink, List<String> list, String annotatedImage){
//sink.next就会手动推送数据
sink.next("<incident>");
for (String data : list) {
// sink.next(data);
// 逐字符发送(可添加延迟模拟打字)
for (char c : data.toCharArray()) {
sink.next(String.valueOf(c));
// 可选:添加短暂延迟(注意:阻塞操作需谨慎,建议用异步延迟)
try {
Thread.sleep(50); // 50ms间隔,可调整
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
sink.next("</incident>");
sink.next("<img>");
sink.next(annotatedImage);
sink.next("</img>");
sink.next("[COMPLETED]");
sink.complete();
}
流式响应效果(逐字返回)

1308

被折叠的 条评论
为什么被折叠?



