英文:
Producing Server Sent Events in Spring Boot Webflux
问题
I have the following code in a SpringBoot application:
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();
}
}
If I navigate to http://localhost (route not shown above but it works)
from there I open DevTools in Chrome and type in the following JavaScript code:
const evtSource = new EventSource("sse/");
evtSource.onmessage = function(event) {
console.log(event.data);
}
But nothing is printed out...
Breakpoints in the map(...)
lambda in MySse::emitEvent
are hit every second
But nothing is printed out in the browser's JS console.
if I visit http://localhost/sse I get the following response:
id:0
event:periodic-event
data:SSE - 20:17:12.972706400
英文:
I have the following code in a SpringBoot application:
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();
}
}
If I navigate to http://localhost (route not shown above but it works)
from there I open DevTools in Chrome and type in the following JavaScript code:
const evtSource = new EventSource("sse/");
evtSource.onmessage = function(event) {
console.log(event.data);
}
But nothing is printed out...
Breakpoints in the map(...)
lambda in MySse::emitEvent
are hit every second
But nothing is printed out in the browswer's JS console.
if I visit http://localhost/sse I get the following response:
id:0
event:periodic-event
data:SSE - 20:17:12.972706400
答案1
得分: 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())));
}
如果您想要流式传输数据,您需要返回一个 Flux
。Mono
表示一个项目,而 Flux
表示0...n
个项目。您触发了 Flux
以每秒的间隔开始发出事件,只要连接保持打开状态,它将每秒向调用客户端发出一个事件。
您可以尝试使用 curl(或者您正在使用的 Chrome 控制台),但如果您使用 curl,则需要使用 -N
标志禁用 curl 的缓冲策略。
curl -N http://localhost:8080/sse
<details>
<summary>英文:</summary>
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())));
}
if you want to stream the data you need to return a `Flux`. A `Mono` is **ONE** item, a `Flux` is `0...n` items. You trigger the `Flux` to start emitting on each second interval and as long as the connection is open it will emit an event back to the calling client each second.
you can try it out with for example curl (or the chrome console as you are using) but you need to disable the curl buffering strategy using the `-N` flag if you are using curl.
curl -N http://localhost:8080/sse
</details>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论