在 spring 中记录慢请求,最直接且标准的方法是使用 webmvcconfigurer 配合 handlerinterceptor。通过重写 posthandle 或 aftercompletion 方法,计算请求处理前后的时间差,当耗时超过设定的阈值(例如 1000 毫秒)时,使用日志框架输出警告信息。这种方式侵入性低,只需配置一个拦截器 bean 即可全局生效,能够准确捕获所有经过 dispatcherservlet 的请求耗时。

如何配置拦截器以捕获特定 URL 的慢请求
要捕获特定 URL 的慢请求,需要在拦截器的 preHandle 方法中记录开始时间,并在 afterCompletion 方法中根据 request.getRequestURI() 判断是否为目标路径。如果匹配且耗时超标,则打印日志。这种方法允许对不同的接口设置不同的监控策略,或者统一对所有接口进行监控。

import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.concurrent.TimeUnit;
@Component
public class SlowRequestInterceptor implements HandlerInterceptor {
private static final long SLOW_THRESHOLD_MS = 1000; // 1秒
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
request.setAttribute("startTime", System.currentTimeMillis());
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) {
// 可以在这里做初步处理,但通常建议在 afterCompletion 中记录,因为那里能获取到异常信息
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
Long startTime = (Long) request.getAttribute("startTime");
if (startTime != null) {
long endTime = System.currentTimeMillis();
long duration = endTime - startTime;
String uri = request.getRequestURI();
if (duration > SLOW_THRESHOLD_MS) {
// 记录慢请求日志
System.out.println(String.format("[SLOW REQUEST] URI: %s, Duration: %d ms", uri, duration));
}
}
}
}
上述代码定义了一个名为 SlowRequestInterceptor 的组件。它在 preHandle 中将当前时间戳存入 HttpServletRequest 属性中。在 afterCompletion 中,它取出该时间戳并计算差值。如果差值大于 SLOW_THRESHOLD_MS,则输出包含 URI 和耗时的日志字符串。这个拦截器需要被注册到 Spring MVC 的配置中才能生效。
如何将拦截器注册到 Spring MVC 配置中
为了让自定义的拦截器生效,必须实现 WebMvcConfigurer 接口,并重写 addInterceptors 方法。在该方法中,将之前定义的 SlowRequestInterceptor 实例添加到拦截器链中。可以通过 addPathPatterns 指定拦截的路径模式,例如 /** 表示拦截所有请求。这一步确保了拦截器逻辑能被 Spring 容器正确加载并应用于 HTTP 请求生命周期。
你是 TypeScript 项目架构专家,专注于脚手架搭建生产就绪的 Node.js 和前端应用。生成包含现代工具链(pnpm、Vite、Next.js)、类型

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Autowired
private SlowRequestInterceptor slowRequestInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(slowRequestInterceptor)
.addPathPatterns("/**"); // 拦截所有请求
}
}
这段代码创建了一个配置类 WebConfig,它实现了 WebMvcConfigurer。通过 @Autowired 注入 SlowRequestInterceptor,并在 addInterceptors 方法中将其注册。这样,所有进入应用的请求都会经过该拦截器,从而实现对慢请求的统一监控。如果需要排除某些静态资源或健康检查接口,可以在 excludePathPatterns 中进行配置。
基于程序中某个输入、条件或结果的具体问题
在实际运行中,如果请求处理过程中抛出异常,afterCompletion 方法中的 ex 参数将不为空。此时,虽然请求失败,但耗时依然可能被记录。这可能导致误报,因为异常导致的超时可能并非业务逻辑慢,而是外部依赖(如数据库或第三方 API)无响应。因此,在记录慢请求时,应区分正常返回和异常返回,以便更准确地定位性能瓶颈。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










