Spring WebFlux请求响应生命周期钩子添加及起止位置确认
Great question—capturing the full request-response lifecycle in reactive frameworks like WebFlux can feel counterintuitive at first, but your initial approach with WebFilter is spot-on. Let’s clarify the right hook points and address your concerns:
Starting Point: First WebFilter is Perfect
Placing your start logic before calling WebFilterChain.filter(exchange) is exactly the right move. As the first filter in the chain, this is the earliest point Spring begins processing the request (right after container-level handling like Tomcat/Netty accepts the connection). This ensures you capture the true start of the request’s journey through your application.
Ending Point: doOnSuccessOrError on the Filter Chain Mono
Your hunch about using doOnSuccessOrError is correct, and it does fire after all downstream processing—including HandlerResultHandler execution and full response body (even chunked) delivery. Here’s why:
- The
Mono<Void>returned bychain.filter(exchange)only completes when the entire reactive processing chain finishes. That includes:- All downstream filters executing
- Controller handler method running
HandlerResultHandlerconverting the handler’s result into a response- All response data (including final chunks in streaming scenarios) being written to the client
Example Implementation
Here’s a concrete, clean way to implement this:
@Component public class RequestTimingFilter implements WebFilter { @Override public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) { long startTime = System.currentTimeMillis(); String path = exchange.getRequest().getPath().value(); return chain.filter(exchange) .doOnSuccess(v -> { long duration = System.currentTimeMillis() - startTime; int status = exchange.getResponse().getStatusCode().value(); System.out.printf("Request %s completed in %dms with status %d%n", path, duration, status); }) .doOnError(error -> { long duration = System.currentTimeMillis() - startTime; System.err.printf("Request %s failed in %dms: %s%n", path, duration, error.getMessage()); }); } }
Key Notes for Chunked/Streaming Responses
For chunked responses (like ServerSentEvent or streaming JSON), the Mono<Void> from chain.filter(exchange) will only complete when the entire stream is exhausted and the last chunk is sent to the client. This means your doOnSuccess callback will trigger exactly when the full response is delivered—exactly what you need.
Why This Works Over Other Hooks
- Avoid using
doOnCompletealone: It won’t capture error scenarios, sodoOnSuccessOrErrorgives you full coverage for both success and failure lifecycles. - This hook is container-agnostic: It works with any reactive web container (Netty, Tomcat, Jetty) since it’s part of Spring WebFlux’s native filter chain.
Final Verdict
Your initial plan is solid:
- Start: Immediately before invoking
chain.filter(exchange)in your firstWebFilter - End: On
doOnSuccessOrErrorattached to theMonoreturned bychain.filter(exchange)
This setup will accurately measure the full request-response lifecycle, from the moment Spring starts processing the request to the moment the last byte of the response is sent to the client.
内容的提问来源于stack exchange,提问作者anuni

