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

在带响应体的WebFilter中使用Spring Data Reactive Repository saveAll()异常

问题分析与解决方案

问题原因

当处理器返回带响应体的ServerResponse时,客户端接收完响应体后可能立即断开连接,触发服务器端响应流的cancel()信号。你当前使用chain.filter(exchange).then(logMessage(exchange))的结构,then操作完全依附于主响应流:当主流被取消时,后续的saveAll流也会被强制取消,导致数据库保存操作中断。而无响应体的场景中,响应流会正常完成,then里的保存操作能顺利执行。

解决方案

有两种可靠方式确保日志保存操作不受响应流取消的影响:

方案1:利用响应提交前回调(确保数据保存后再发送响应)

将日志保存操作注册到响应提交前的回调中,无论响应是正常完成还是被取消,都会执行该操作,且会等待操作完成后再提交响应,保证数据能成功写入数据库:

修改LogWebFilter的filter方法:

@NonNull
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
    // 注册响应提交前的回调,确保日志保存完成后再发送响应
    exchange.getResponse().beforeCommit(() -> logMessage(exchange));
    return chain.filter(exchange);
}

方案2:异步执行日志操作(不阻塞响应发送)

如果不需要等待日志保存完成再返回响应,可以用doFinally在流结束(无论完成还是取消)时异步执行日志操作,脱离主响应流的生命周期:

@NonNull
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
    return chain.filter(exchange)
            .doFinally(signalType -> {
                logMessage(exchange)
                        .subscribeOn(Schedulers.boundedElastic())
                        .subscribe(
                                null,
                                err -> log.error("保存操作日志失败", err)
                        );
            });
}

额外检查

你的UserOperationLog实体类中isNew()始终返回true,这符合新增数据的场景,但需确保id字段配置了数据库自动生成规则(比如自增),否则可能导致保存失败。从无响应体场景的正常表现来看,这部分应该没有问题。

内容的提问来源于stack exchange,提问作者Peter Balogh

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 13:05:10