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

Spring WebFlux REST API(注解控制器)请求总处理时间统计咨询

嘿,这个需求很常见,用Spring WebFlux的WebFilter完全能搞定,我给你一步步拆解实现方法:

核心思路

WebFlux是响应式编程模型,所以我们需要在请求进入时记录起始时间,然后监听响应的完成信号(不管成功还是失败),再计算时间差。ServerWebExchange自带的属性Map正好可以用来存储每个请求的起始时间,它是请求级别的,完全不用担心线程安全问题。

具体实现代码

先写一个自定义的WebFilter,Spring会自动把它加入到过滤器链中:

import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilter;
import org.springframework.web.server.WebFilterChain;
import reactor.core.publisher.Mono;
import java.time.Instant;
import java.time.Duration;

@Component
public class RequestTimingFilter implements WebFilter {

    // 定义属性键的常量,避免硬编码
    private static final String REQUEST_START_TIME = "REQUEST_START_TIME";

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
        // 1. 记录请求起始时间,存入ServerWebExchange的属性中
        Instant startTime = Instant.now();
        exchange.getAttributes().put(REQUEST_START_TIME, startTime);

        // 2. 继续执行后续的过滤器和控制器逻辑
        return chain.filter(exchange)
                // 3. 响应成功完成时计算时长
                .doOnSuccess(aVoid -> calculateAndLogDuration(exchange, startTime))
                // 4. 请求出错时也要统计时长
                .doOnError(throwable -> {
                    calculateAndLogDuration(exchange, startTime);
                    System.err.printf("请求 %s 处理失败,错误信息: %s%n",
                            exchange.getRequest().getPath(), throwable.getMessage());
                });
    }

    private void calculateAndLogDuration(ServerWebExchange exchange, Instant startTime) {
        Instant endTime = Instant.now();
        Duration duration = Duration.between(startTime, endTime);
        long durationMillis = duration.toMillis();
        
        // 这里可以替换成日志框架(如SLF4J),或者上报到监控系统
        System.out.printf("请求路径: %s,HTTP方法: %s,处理总时长: %d ms%n",
                exchange.getRequest().getPath(),
                exchange.getRequest().getMethod(),
                durationMillis);
        
        // 可选:把时长放到响应头返回给客户端
        exchange.getResponse().getHeaders().add("X-Request-Duration", String.valueOf(durationMillis));
    }
}

关键细节解释

  • 存储起始时间:用exchange.getAttributes()获取请求级别的Map,把起始时间存进去,每个请求的属性都是独立的,不会互相干扰。
  • 响应式监听:因为WebFlux是异步的,必须通过doOnSuccess和doOnError来监听响应的完成信号,不能像Servlet那样在过滤器末尾直接计算(那样会拿到错误的时间,因为请求还没处理完)。
  • 异常场景覆盖:不管请求成功还是失败,都要统计时长,所以两个回调都要处理。
  • 精确时间计算:用Instant和Duration比System.currentTimeMillis()更精确,适合需要细粒度监控的场景。

额外扩展

如果需要更复杂的监控(比如按接口统计平均时长、QPS等),可以把时长数据存入Micrometer这类监控工具,结合Prometheus+Grafana做可视化,但基础的统计逻辑就是上面这样。

内容的提问来源于stack exchange,提问作者Leo Prince

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 07:22:12