在 Spring Boot Webflux 中生成服务器发送事件

aus*_*ser 4 java spring-boot spring-webflux

我在 SpringBoot 应用程序中有以下代码:

class MySse {
    public Mono<ServerResponse> emitEvents(ServerRequest request){
        return ServerResponse.ok()
                .contentType(MediaType.TEXT_EVENT_STREAM)
                .body(Mono.from(Flux.interval(Duration.ofSeconds(1))
                .map(sequence  -> ServerSentEvent.builder()
                        .id(String.valueOf(sequence))
                        .event("periodic-event")
                        .data("SSE - " + LocalTime.now().toString())
                        .build())), ServerSentEvent.class);
    }
}

@Configuration
public class MyRoutesConfiguration {

    @Autowired
    @Bean
    RouterFunction<ServerResponse> sseRoute(MySse mySse) {
        return route(path("/sse").and(method(HttpMethod.GET)), MySse ::emitEvents)
                ;
    }

    @Bean
    public MySse mySse() {
        return new MySse();
    }
}
Run Code Online (Sandbox Code Playgroud)

如果我从那里导航到 http://localhost(上面未显示路线,但它可以工作),我会在 Chrome 中打开 DevTools 并输入以下 JavaScript 代码:

const evtSource = new EventSource("sse/");
evtSource.onmessage = function(event) {
  console.log(event.data);
}
Run Code Online (Sandbox Code Playgroud)

但什么也没打印出来...

每秒都会命中map(...)lambda中的断点MySse::emitEvent

但浏览器的 JS 控制台中没有打印任何内容。

如果我访问 http://localhost/sse 我会得到以下响应:

id:0
event:periodic-event
data:SSE - 20:17:12.972706400
Run Code Online (Sandbox Code Playgroud)

Tho*_*olf 5

public Mono<ServerResponse> emitEvents(ServerRequest request){

    return ServerResponse.ok()
            .contentType(MediaType.TEXT_EVENT_STREAM)
            .body(BodyInserters.fromServerSentEvents(Flux.interval(Duration.ofSeconds(1))
            .map(aLong -> ServerSentEvent.<String>builder()
                            .id(String.valueOf(aLong))
                            .event("periodic-event")
                            .data("SSE - " + LocalTime.now().toString())
                            .build())));
}
Run Code Online (Sandbox Code Playgroud)

如果你想流式传输数据,你需要返回一个Flux. AMono一个项目,aFlux0...n项目。您可以触发Flux以每秒间隔开始发出,只要连接打开,它就会每秒向调用客户端发出一个事件。

您可以使用例如curl(或您正在使用的chrome控制台)进行尝试,但-N如果您使用curl,则需要使用该标志禁用curl缓冲策略。

curl -N http://localhost:8080/sse
Run Code Online (Sandbox Code Playgroud)