news 2026/6/21 17:20:16

【后端】【Java】《Spring Boot 统一接口耗时统计实践:基于 HandlerInterceptor 的工程级方案》

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【后端】【Java】《Spring Boot 统一接口耗时统计实践:基于 HandlerInterceptor 的工程级方案》

一步一步讲清楚
👉接口耗时为什么不能写在 Controller 里?
👉在拦截器里应该怎么“正确、优雅地处理”?


一、为什么不在 Controller 里写耗时代码?

示例代码是这样的:

long start = System.currentTimeMillis(); // 业务逻辑 long cost = System.currentTimeMillis() - start; log.info("接口耗时: {} ms", cost);

❌ 问题有 4 个:

  1. 大量重复代码

    • 每个接口都要写一遍

  2. 业务代码被日志污染

  3. 容易漏写 / 写错

  4. 无法统一统计所有接口

👉这是典型的横切关注点(Cross-Cutting Concern)
👉 非常适合用:拦截器 / AOP


二、正确方案:在拦截器中统一记录接口耗时

Spring MVC 中,拦截器(HandlerInterceptor)是最合适的位置


三、拦截器记录耗时的核心思路

preHandle → 记录开始时间 controller → 业务逻辑 afterCompletion → 计算耗时 + 打日志

四、标准实现方式(推荐写法)

1️⃣ 在 preHandle 中记录开始时间

@Component public class TimeCostInterceptor implements HandlerInterceptor { private static final Logger log = LoggerFactory.getLogger(TimeCostInterceptor.class); private static final String START_TIME = "startTime"; @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { request.setAttribute(START_TIME, System.currentTimeMillis()); return true; }

2️⃣ 在 afterCompletion 中计算耗时

@Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { Long startTime = (Long) request.getAttribute(START_TIME); if (startTime == null) { return; } long cost = System.currentTimeMillis() - startTime; log.info("接口耗时 | {} {} | {} ms", request.getMethod(), request.getRequestURI(), cost); } }

3️⃣ 注册拦截器

@Configuration public class WebConfig implements WebMvcConfigurer { @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new TimeCostInterceptor()) .addPathPatterns("/**") .excludePathPatterns("/static/**"); } }

五、最终日志效果(真实可用)

2025-01-01 10:00:01.456 INFO [traceId=9f8a3b7c2d1a4e] 接口耗时 | GET /users/1 | 38 ms

✔ 不侵入 Controller
✔ 所有接口自动统计
✔ 日志格式统一


六、和 TraceId(链路追踪)如何配合?

如果你已经使用了MDC + TraceId(前一篇博客内容):

MDC.put("traceId", traceId);

那么这里的耗时日志会自动带上 TraceId,无需额外处理。

👉 这就是为什么:

  • TraceFilter

  • TimeCostInterceptor

要一起使用


七、进阶优化(生产环境强烈推荐)

1️⃣ 慢接口告警(非常实用)

if (cost > 1000) { log.warn("慢接口 | {} {} | {} ms", request.getMethod(), request.getRequestURI(), cost); }

2️⃣ 区分正常 / 异常请求

if (ex != null) { log.error("接口异常 | {} {} | {} ms", request.getMethod(), request.getRequestURI(), cost, ex); }

3️⃣ 只统计 Controller 方法

if (!(handler instanceof HandlerMethod)) { return; }

避免静态资源、错误页面干扰统计。


八、拦截器 vs AOP,该选哪个?

场景推荐
统计接口耗时✅ 拦截器
记录方法级别日志AOP
参数 / 返回值埋点AOP
接口级统一日志✅ 拦截器

👉HTTP 接口维度 = 拦截器最合适


九、一句话总结(面试 / 实战都能用)

接口耗时属于横切关注点,
应统一在 Spring MVC 拦截器中处理,
避免侵入 Controller 业务逻辑。


版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/21 20:43:56

45、对等网络文件共享与网关互通性解析

对等网络文件共享与网关互通性解析 在当今数字化时代,对等(P2P)网络文件共享技术发展迅速,不同的文件共享网络各具特点和优势,但也存在一些不足之处。本文将深入探讨几种常见的P2P文件共享网络,包括Freenet、Gnutella、Mojo Nation、Free Haven和Publius,并分析在它们之…

作者头像 李华
网站建设 2026/6/20 22:48:05

实验实验实验实验。

这莫名其妙的问题还是没解决,不知道为什么这个路径没有,而且文章也被锁了。这是小程序运行时产生的文件夹。现在目录变了。太阴了充钱才给你看文件。小程序目录下的 1457 文件夹为空,核心是文件未同步/编译失败、路径指向错误、权限限制或文件…

作者头像 李华
网站建设 2026/6/19 18:34:17

1、掌握 Puppet 4:高效管理 IT 基础设施的秘诀

掌握 Puppet 4:高效管理 IT 基础设施的秘诀 1. Puppet 简介 在当今不断发展的软件行业中,DevOps 趋势正深刻改变着工作流程。开发者自行搭建和维护环境,运维人员则将自动化提升到新高度,把整个基础设施转化为代码。Puppet 作为一款新兴的服务器配置管理工具,凭借其独特的…

作者头像 李华
网站建设 2026/6/15 0:07:31

【网络安全】四、Sniffer网络安全检测

一、实验目的利用 Sniffer 软件捕获网络信息数据包,通过对数据包分层解析进行状态分析,深入理解网络数据传输的底层逻辑。学会网络安全检测工具(Sniffer)的实际操作方法,能够独立完成检测报告,并基于检测结…

作者头像 李华
网站建设 2026/6/20 3:22:22

REST--GCA

Voxel wise和ROI wise REST 提供两种计算功能连接的方式:Voxel wise(计算 ROI 和 mask 内每个体素的相关)和 ROI wise(计算两个或多个 ROI 之间的相关)。 Mask 的设定 有三种类型 mask:默认的 mask、无 mas…

作者头像 李华