1.通过时间戳。System.currentTimeMillis()
记录开始时间时间戳
执行业务逻辑
记录结束时间时间戳
然后相差的时间戳就是耗时
返回毫秒级时间戳
优点:简单好用
缺点: 精度有限,受服务器时间影响(如果第一次是北京时间,然后服务器时间被调整了第二次的结尾的时间戳就不匹配了就有误差了)
代码侵入性强。
2.System.nanoTime()
高精度的时间戳
提供纳秒级别的测量精度,而且不受服务器时间影响。
缺点:需要进行单位转换,代码侵入性强。
3.AOP
使用AOP解决了上面那些的代码侵入缺点,然后和他们联用。
缺点:只能在spring上面用,而且有一定的性能开销
4.SpringMVC 拦截器实现接口耗时统计(HandlerInterceptor)
一、拦截器执行节点(三层回调)
-
preHandle(请求刚进到 Controller 之前) 请求经过 Servlet、分发器,还没进到接口业务代码,在这里记录 nano 起始值,用 ThreadLocal 绑定当前线程保存时间。
-
执行业务接口完整逻辑(Controller→Service→DAO)。
-
**afterCompletion(整个请求全部结束,响应已经返回浏览器,异常与否都会进这个方法)**取出之前存的起始纳秒,拿当前 nano 减去起始数值,换算成毫秒,就是整个接口总耗时;最后清空 ThreadLocal 防止内存泄露。
postHandle 只在正常无异常、没返回前触发,异常不会走,所以耗时统一在 afterCompletion 统计。
二、计时选型逻辑
- 耗时计算:nanoTime只算时间流逝,运维修改服务器系统时间、时区变更、NTP 回拨时钟,完全不影响差值,不会出现负耗时。
- 如需记录请求发生日期:currentTimeMillispreHandle 顺带存时间戳,用来记录这条请求是什么时间点发起的,仅用于落地日志时间。
三、拦截器和 AOP 层级区别
- 拦截器:URL 请求层面,拦整条 HTTP 请求,统计从请求进入容器到响应结束全链路耗时(包含参数解析、视图处理);
- AOP:Controller 方法层面,只统计接口方法内部代码执行时间,不算 Servlet 前置解析耗时。
5.Filter 耗时统计:
- Filter 实现代码.
java
import jakarta.servlet.*;
import jakarta.servlet.annotation.WebFilter;
import jakarta.servlet.http.HttpServletRequest;
import java.io.IOException;
@WebFilter("/*")
public class TimeCostFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {
// 放行前记录纳秒时间
long start = System.nanoTime();
try {
// 放行:执行拦截器、Controller、业务全流程
filterChain.doFilter(request, response);
} finally {
// 请求结束计算耗时
long costMs = (System.nanoTime() - start) / 1_000_000;
HttpServletRequest req = (HttpServletRequest) request;
System.out.println("接口:"+req.getRequestURI()+",全链路耗时:"+costMs+"ms");
}
}
}
SpringBoot 项目直接加@WebFilter("/*")自动注册,无需额外配置类。
2. 优点
- 层级最外层:统计 Tomcat 内部全链路耗时(Filter→拦截器→Controller→Service→DB),统计范围最全;
- 原生 Servlet 规范:脱离 Spring 也能用,SSM、SpringBoot 通用;
- 使用
nanoTime,服务器修改系统时间不会出现负耗时; - 可统一处理编码、跨域响应头、IP 黑名单拦截、改写请求报文。
3. 缺点
- 只能获取 Request/Response,拿不到 Controller 方法名、注解、接口入参,精细化日志难做;
- 只能按 URL 路径拦截,无法精准控制某个 Controller 方法;
- 只统计容器内部耗时,前端到服务器的网络传输耗时无法统计。
4. 使用场景
全局服务性能监控、统一响应封装、IP 限流
6.Micrometer + APM 方案(生产正式做接口耗时,企业主流)
一、流程
- 引入 Micrometer 依赖:SpringBoot 自带 micrometer,配合 actuator 监控包
- 框架自动采集接口耗时指标 :不用自己写 Filter / 拦截器 / AOP 计时,SpringMVC 底层自动埋点,自动统计每个接口平均耗时、QPS、异常率
- 项目暴露 Prometheus 接口 (/actuator/prometheus),把指标数据对外输出
- Prometheus 定时拉取数据 + Grafana 图表展示 / SkyWalking 全链路追踪
二、优点
- 零侵入代码:不用手写计时代码,框架原生自动采集接口耗时,比自己写 Filter、拦截器靠谱
- 生产级能力:不只统计耗时,还统计请求量、报错数、慢请求、并发数
- 支持分布式:配合 SkyWalking、Zipkin 做跨服务全链路耗时追踪(微服务调用链)
- 低性能开销:底层优化,监控几乎不影响业务性能
- 数据聚合:自动汇总日 / 小时平均耗时、P95/P99 慢接口(面试高频:百分位耗时)
三、缺点
- 配置繁琐:需要部署 Prometheus、Grafana 一套组件,中小型单体项目没必要大动干戈
- 上手成本高:要懂监控组件部署、告警规则配置,小项目简单打印日志就够用
四、和前面三种(Filter / 拦截器 / AOP)对比
- Filter/Interceptor/AOP:自定义手写代码,适合自测、简单日志打印,小项目
- Micrometer+APM:框架原生自动采集 + 可视化大盘 ,线上生产环境标准方案,大厂微服务必用
五、面试一句话区分
- 自己写 Filter / 拦截器:开发自测、简单日志耗时
- Micrometer+Prometheus/SkyWalking:线上生产环境标准化监控耗时