Photo by sthr ngn on Unsplash
Spring Boot 中实现服务端主动数据推送
author's avatar
igaozp
未来已来,只是分布不均

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

ndjson

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

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

代码示例

@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 支持。

@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