You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Flux+SSE流数据开发问题咨询及格式支持需求

Hey there! Let's work through your Spring Flux + SSE issues step by step, plus get the content type support you need sorted out.

1. Fixing Chrome's Persistent Loading Spinner (Connection Not Closing After Flux Completion)

The issue here is that even though your Flux.fromIterable sends a complete signal, Chrome's native SSE handling (or Spring's default response headers) might make the browser think more data is on the way. To fix this, you should explicitly use Spring's ServerSentEvent wrapper to format responses properly for SSE, and tweak headers to tell the browser the connection will close once all data is sent.

Here's the adjusted code:

@Controller("/")
@Validated
public class HelloController {

    // Add both content types to the produces annotation
    @Produces({MediaType.TEXT_EVENT_STREAM, MediaType.APPLICATION_STREAM_JSON})
    @Get("/hello/{name}")
    public Flux<ServerSentEvent<Hello>> hello(@NotBlank String name, ServerHttpResponse response) {
        // Set headers to prevent browser caching and signal connection closure
        response.getHeaders().set(HttpHeaders.CACHE_CONTROL, "no-cache, no-store, must-revalidate");
        response.getHeaders().set(HttpHeaders.CONNECTION, "close");

        List<Hello> list = new ArrayList<>();
        list.add(new Hello("test1", 1));
        list.add(new Hello("test2", 2));

        return Flux.fromIterable(list)
                // Wrap each Hello object in a ServerSentEvent for proper SSE formatting
                .map(hello -> ServerSentEvent.builder(hello).build())
                .doOnComplete(() -> {
                    System.out.println("response should be closed here!");
                });
    }
}

Using ServerSentEvent ensures your responses follow the SSE spec, which Chrome's EventSource client understands correctly. Once the Flux completes, the connection will close immediately, and the loading spinner will stop.

2. Preventing Auto-Timeout After 1 Minute

That 1-minute cutoff is likely from Netty's default connection timeout (used by Spring WebFlux under the hood). To make the connection only close when your Flux sends the onComplete signal, disable this timeout in your configuration.

Add these settings to your application.properties:

# Disable Netty's server connection timeout (no auto-close)
spring.netty.server.connection-timeout=-1

# Ensure WebFlux doesn't enforce a reactive timeout on responses
spring.webflux.reactive.timeout=-1

This tells the server to keep the connection open until your Flux explicitly completes, rather than closing it after a fixed duration.

3. Supporting application/stream+json

As shown in the code above, we added MediaType.APPLICATION_STREAM_JSON to the @Produces annotation. This lets clients request either SSE (text/event-stream) or a raw JSON stream (application/stream+json) by setting the Accept header in their request:

  • If the client sends Accept: text/event-stream, they'll get properly formatted SSE events.
  • If they send Accept: application/stream+json, they'll get a newline-separated stream of JSON objects (each Hello instance serialized to JSON).

Just make sure your Hello class has proper getter methods (or use Lombok's @Data annotation) so Spring can serialize it to JSON correctly.


内容的提问来源于stack exchange,提问作者Aleksey Kozel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 07:41:26