流式接口通常用于持续不断地传输数据,例如推送日志、实时监控数据、消息订阅等场景。本文提供两种常见的实现方案:使用 Servlet 方式的 Server-Sent Events (SSE)(采用 SseEmitter 对象)以及基于响应式编程的 Spring WebFlux(利用 Flux 流)。
【前提条件】
- 已安装 JDK 8 及以上版本。
- 使用 Maven 或 Gradle 构建 Spring Boot 项目。
- 理解基本的 Spring Boot 开发流程以及 REST API 的开发。
【方案一:基于 SseEmitter 实现 SSE 流式接口】
SseEmitter 是 Spring MVC 提供的一个工具类,可以很方便地实现服务端向客户端单向推送数据。下面给出一个简单的示例代码:
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
import java.io.IOException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
@RestController
public class SseStreamController {
@GetMapping("/stream/sse")
public SseEmitter streamSse() {
// 设置 SseEmitter 默认超时时间为 30 分钟
SseEmitter emitter = new SseEmitter(30 * 60 * 1000L);
// 使用线程池异步发送数据
ExecutorService executor = Executors.newSingleThreadExecutor();
executor.execute(() -> {
try {
for (int i = 1; i <= 10; i++) {
// 构造数据,比如这里发送纯文本消息
String data = "当前 event 数据:" + i;
emitter.send(data);
// 模拟延时,1 秒一条数据
Thread.sleep(1000);
}
// 所有数据发送完成后关闭 emitter
emitter.complete();
} catch (IOException | InterruptedException e) {
emitter.completeWithError(e);
} finally {
executor.shutdown();
}
});
return emitter;
}
}
【说明】
- 客户端请求【GET /stream/sse】时,将会建立一个 SSE 连接。
- 服务器在独立线程中每秒发送一条消息,客户端能实时接收到数据。
- 流程结束后,通过 emitter.complete() 通知客户端数据发送完毕。
在前端页面中,可以通过 JavaScript 的 EventSource 对象来订阅该 SSE 流,例如:
const eventSource = new EventSource('/stream/sse');
eventSource.onmessage = function(event) {
console.log("接收到数据:", event.data);
};
eventSource.onerror = function(err) {
console.error("错误:", err);
};
【方案二:基于 Spring WebFlux 实现 Reactive 流式接口】
Spring WebFlux 提供响应式编程支持,通过 Reactor 的 Flux 能够轻松实现流式数据传输。示例如下:
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;
import java.time.Duration;
@RestController
public class ReactiveStreamController {
@GetMapping(value = "/stream/flux", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<String> streamFlux() {
// 每隔 1 秒发送一条数据,共发送 10 条
return Flux.interval(Duration.ofSeconds(1))
.map(sequence -> "响应式流数据:" + (sequence + 1))
.take(10);
}
}
【说明】
- 在 @GetMapping 中设置 produces = MediaType.TEXT_EVENT_STREAM_VALUE 表示以 SSE 格式推送数据。
- Flux.interval(...) 每隔一秒生成一个递增的数字序列,然后通过 map 操作转换成字符串消息。
- take(10) 限制只发送 10 个数据,流结束后自动关闭。
这种方式适用于响应式编程,并且可以充分利用 Reactor 框架的特性实现复杂数据流逻辑。
──────────────────────────────
【项目配置说明】
如果选择方案一(SseEmitter),确保在 pom.xml 中引入 spring-boot-starter-web:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>
如果选择方案二(基于 WebFlux),则需要引入 spring-boot-starter-webflux:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-webflux</artifactId> </dependency>
根据需求选择对应方案,如果项目中同时需要传统 MVC 和响应式编程,建议了解二者的区别,并合理拆分接口与模块。
──────────────────────────────
【调试与测试】
- 直接运行 Spring Boot 项目后,通过浏览器或 Postman 访问:
• SSE 示例地址:http://localhost:8080/stream/sse
• Flux 示例地址:http://localhost:8080/stream/flux - 使用开发者工具或前端代码观察持续流式数据的显示。
──────────────────────────────
【总结】
本文介绍了两种在 Java Spring Boot 中发布流式接口的方法:
• 基于 SseEmitter 实现基于 Servlet 的 Server-Sent Events;
• 基于 Spring WebFlux 与 Reactor 的响应式数据流。
两种方式各有优点:SseEmitter 写法简单适用于传统 Spring MVC 场景,而 Spring WebFlux 更适合构建高并发与响应快速的实时数据推送服务。开发者可根据项目需求选择合适的实现方式,最终实现实时向客户端推送数据的流式接口。
希望本文对你在 Java Spring Boot 中实现流式接口有所帮助。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。