Spring Boot 中实现服务端主动数据推送

在日常开发中通常使用 WebSocket 实现服务端的主动地数据推送,这里简单介绍两种其他的数据推送方案,ndjsonSSE

ndjson

ndjson 全称 Newline Delimited JSON,即使用换行符分割的 JSON,同时能够保证每一行的内容都是一个完整的 JSON。这里使用 ndjson 并不是因为它可以实现服务端数据推送,而是凭借 ndjson 的数据格式的特性,作为服务端的 JSON 数据流的数据输出,来更好地帮助我们实现数据推送的效果。

这里使用 Spring Boot 作为基础的服务端框架,简单演示一下相关代码及功能。首先要确保项目依赖中包含 spring-boot-starter-webflux 依赖包。

代码示例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
@GetMapping(value = "ndjson", produces = MediaType.APPLICATION_NDJSON_VALUE)
Flux<Data> ndjson() {
    return dataStream();
}

private Flux<Data> dataStream() {
    return Flux.interval(Duration.ofSeconds(1))
            .take(5)
            .map(i -> new Data(i, Instant.now()));
}

代码中定义了一个私有方法用来生成数据流,效果是每隔 1 秒生成一条数据。在 @GetMapping中指定了 MediaType.APPLICATION_NDJSON_VALUE 作为数据的响应格式。

SSE

SSE 全称 Server-sent events,即服务器发送事件,服务端可使用 SSE 生成相应的数据流。

代码示例,同样需要 WebFlux 支持。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
@GetMapping(value = "sse", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
Flux<Data> sse() {
    return dataStream();
}

private Flux<Data> dataStream() {
   return Flux.interval(Duration.ofSeconds(1))
            .take(5)
            .map(i -> new Data(i, Instant.now()));
}

ndjson 方案唯一的不同是,数据响应的格式替换为了MediaType.TEXT_EVENT_STREAM_VALUE

总结

虽然 ndjsonSSE 方案都可以实现服务端的数据推送,但这两种的数据通信都是单向通信,只能从服务端到客户端,无法实现双向通信,需要根据自身的场景需要酌情考虑使用。

项目的完整代码可参考 StreamJsonController

参考内容

https://nurkiewicz.com/2021/08/json-streaming-in-webflux.html

https://www.ruanyifeng.com/blog/2017/05/server-sent_events.html

comments powered by Disqus
Built with Hugo
主题 StackJimmy 设计