contentLengthFilterRegistrationBean导致SSE连接断开

好好的SSE代码复制到项目里直接发送消息可以,却无法异步发消息,经过痛苦的排查发现有人加了过滤器给所有请求加了Content-Length头,导致SSE连接中断,因为在 SSE 请求上强制添加 Content-Length,浏览器会认为响应已经结束,导致后续数据无法接收。所以异步发送消息接收不到是因为连接已经断了。解决方案是在过滤器中识别SSE请求(通过Accept: text/event-stream头部或特定路径),对其响应跳过Content-Length设置,以确保连接持续可用。

修改过滤器:
// 如果是 SSE 请求,直接放行
if (request.getRequestURI().contains(“/sse”) ||
“text/event-stream”.equalsIgnoreCase(request.getHeader(“Accept”))) {
filterChain.doFilter(request, response);
return;
}

——————————————————————
我的SSE demo
sse后台

@GetMapping(value = "/stream-sse-doc/sse", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public SseEmitter streamSse() throws IOException {
    SseEmitter emitter = new SseEmitter(30_000L); // 30秒超时

    // 初始消息
    emitter.send("begin\n");

    // 启动一个线程手动发送消息
    new Thread(() -> {
        try {
            emitter.send("Hello\n");
            Thread.sleep(500);

            for (int i = 0; i < 10; i++) {
                emitter.send(i + "Reactor\n");
                Thread.sleep(1000);
            }
            emitter.complete();
        } catch (Exception e) {
            emitter.completeWithError(e);
        }
    }).start();

    return emitter;
}

前台直接浏览器请求即可,也可以js请求:

 // 替换为你的后端接口地址
const eventSource = new EventSource("http://localhost:19400/myproject/stream-sse-doc/sse");

// 监听消息事件
eventSource.onmessage = function(event) {
	try {
		const data =  event.data ;
		console.log("收到 SSE 数据:", data);
	} catch (e) {
		console.error("解析数据失败:", e);
	}
};

// 监听自定义事件(如果后端发送了带事件名的数据)
eventSource.addEventListener("progress-update", function(event) {
	try {
		const data =  event.data ;
		console.log("收到自定义事件 'progress-update':", data);
	} catch (e) {
		console.error("解析自定义事件数据失败:", e);
	}
});

// 监听错误
eventSource.onerror = function() {
	console.error("SSE 连接出错");
	eventSource.close(); // 关闭连接
};

另外发现有sse不实时返回,而是结束的时候一次全返回的,这个要在nginx里关闭缓存。

你可能感兴趣的:(contentLengthFilterRegistrationBean导致SSE连接断开)