如何在RouterFunction执行完成后通过ServerResponse执行逻辑?(doOnNext未生效)
解决方案
你遇到的问题是因为ServerResponse是延迟渲染的,doOnNext仅在Mono<ServerResponse>发射元素时触发,但此时响应还未实际写入客户端,甚至可能因为操作符的冷流特性导致回调未执行。要在RouterFunction执行完成(即响应已发送给客户端)后执行逻辑,正确的实现方式是包装ServerResponse并重写其writeTo方法,在响应写入完成后触发后续逻辑:
public HandlerFilterFunction<ServerResponse, ServerResponse> addMetrics() { return (request, next) -> next.handle(request) .map(response -> new ServerResponseDecorator(response) { @Override public Mono<Void> writeTo(ServerWebExchange exchange, Context context) { // 先完成原响应的写入操作,写入完成后执行指标收集 return super.writeTo(exchange, context) .doOnSuccess(unused -> meterService.addMetric(this)); } }); }
为什么之前的方案无效?
doOnNext是在Mono发射ServerResponse对象时执行,此时响应还未开始写入客户端,甚至如果后续没有订阅这个Mono(比如框架内部的订阅逻辑有差异),doOnNext根本不会触发。- 而通过
ServerResponseDecorator重写writeTo方法,我们能确保逻辑在响应实际写入完成后执行,这才是真正的"RouterFunction执行完成"的时机。
另外,如果你不需要等待响应写入完成,只是想在RouterFunction处理完请求、生成ServerResponse对象后立即执行逻辑,可以用doOnSuccess替代doOnNext,它会在Mono成功发射元素时可靠触发:
public HandlerFilterFunction<ServerResponse, ServerResponse> addMetrics() { return (request, next) -> next.handle(request) .doOnSuccess(response -> meterService.addMetric(response)); }
需要注意的是,这种方式的逻辑执行时机是在响应对象生成后、写入客户端前,根据你的实际需求选择即可。
内容的提问来源于stack exchange,提问作者Oleksandr Onopriienko
相关产品推荐
相关产品推荐

