SpringBoot 统计API接口用时该使用过滤器还是拦截器?

统计请求的处理时间(用时)既可以使用 Servlet 过滤器(Filter),也可以使用 Spring 拦截器(Interceptor)。两者都可以在请求处理前后插入自定义逻辑,从而实现对请求响应时间的统计。

使用建议

如果你需要在更底层、与框架无关的地方记录所有请求(包括静态资源请求)的处理时间,那么 Servlet 过滤器是一个更好的选择。

如果你正在使用 Spring MVC 并且关注的是 Controller 层的处理时间,或者需要访问到 Spring 上下文中的服务,那么 Spring 拦截器可能更为合适。

代码样例

Servlet 过滤器(Filter)

import jakarta.servlet.*;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;import java.io.IOException;
import java.time.Instant;// @Component 注册时会new 这里无需指定 registration.setFilter(new LogFilter());
@Slf4j
public class LogFilter implements Filter {@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {System.err.println("***LogFilter.doFilter.start***");HttpServletRequest httpReq = (HttpServletRequest) request;long startTime = Instant.now().toEpochMilli();// 记录请求开始时间及请求信息log.warn("LogFilter.doFilter: Start processing request at {} - {}", Instant.now(), httpReq.getRequestURI());try {// 将请求传递给下一个过滤器或目标资源chain.doFilter(request, response);} finally {// 记录请求结束时间及响应状态码long endTime = Instant.now().toEpochMilli();int statusCode = ((HttpServletResponse) response).getStatus();log.warn("LogFilter.doFilter: Finished processing request at {} - {} in {} ms. Status code: {}", Instant.now(), httpReq.getRequestURI(), (endTime - startTime), statusCode);}System.err.println("***LogFilter.doFilter.end***");}
}

注册过滤器(Filter)

@Configuration
public class AppConfig {@Beanpublic FilterRegistrationBean<LogFilter> tokenFilterRegistration() {FilterRegistrationBean<LogFilter> registration = new FilterRegistrationBean<>();registration.setFilter(new LogFilter());// 可以设置过滤器名称registration.setName("logFilter");// 设置拦截规则registration.addUrlPatterns("/*"); // 拦截所有请求// 设置过滤器执行顺序,默认为0,数值越小优先级越高registration.setOrder(1);return registration;}
}

Spring 拦截器(Interceptor)

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;import java.time.Instant;@Component
@Slf4j
public class LogInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {System.err.println("***LogInterceptor.preHandle***");long startTime = Instant.now().toEpochMilli();request.setAttribute("startTime", startTime);log.warn("LogInterceptor.postHandle: Start processing request at {} - {}", Instant.now(), request.getRequestURI());return true;}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) {System.err.println("***LogInterceptor.preHandle***");// 获取请求开始时间Long startTime = (Long) request.getAttribute("startTime");if (startTime != null) {long executionTime = Instant.now().toEpochMilli() - startTime;int statusCode = response.getStatus();log.warn("LogInterceptor.postHandle: Finished processing request at {} - {} in {} ms. Status code: {}", Instant.now(), request.getRequestURI(), executionTime, statusCode);}}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {System.err.println("***LogInterceptor.afterCompletion***");// 在此可以添加额外的后处理逻辑,但本例中我们不需要}
}

注册拦截器(Interceptor)

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {@Autowiredprivate ResponsePostInterceptor responsePostInterceptor;@Autowiredprivate LogInterceptor logInterceptor;/*** 为拦截器注册表添加拦截器** @param registry 拦截器注册表*/@Overridepublic void addInterceptors(InterceptorRegistry registry) {// 在Spring MVC配置中注册一个名为responsePostInterceptor的拦截器,使其能够对匹配路径“/**”(即对应用程序中的所有路径)的请求进行拦截registry.addInterceptor(responsePostInterceptor).addPathPatterns("/**");registry.addInterceptor(logInterceptor).addPathPatterns("/**");}
}

[Ref] 在Spring Boot中注册过滤器几种方式

测试验证

在这里插入图片描述

在这里插入图片描述

# 过滤器开始计时
***LogFilter.doFilter.start***
[2024-01-17 08:17:55] [WARN ] [http-nio-8080-exec-2] [LogFilter.java:22][LogFilter.doFilter: Start processing request at 2024-01-17T00:17:55.662652400Z - /students]
***RequestHeaderCheckFilter.doFilter.start***# 拦截器组的 preHandle
***ResponsePostInterceptor.preHandle***
# log用时拦截器开始计时
***LogInterceptor.preHandle***
[2024-01-17 08:17:55] [WARN ] [http-nio-8080-exec-2] [LogInterceptor.java:20][LogInterceptor.postHandle: Start processing request at 2024-01-17T00:17:55.852229500Z - /students]# Controller层
***StudentController.edit***
[2024-01-17 08:17:56] [INFO ] [http-nio-8080-exec-2] [HikariDataSource.java:110][practisedb - Starting...]
[2024-01-17 08:17:56] [INFO ] [http-nio-8080-exec-2] [HikariPool.java:565][practisedb - Added connection com.mysql.cj.jdbc.ConnectionImpl@34a6ebfc]
[2024-01-17 08:17:56] [INFO ] [http-nio-8080-exec-2] [HikariDataSource.java:123][practisedb - Start completed.]# @ControllerAdvice对Response增强,比如修改状态码,补充header值
***ResponsePostAdvice.supports***
***ResponsePostAdvice.beforeBodyWrite***# 拦截器组的 postHandle
***LogInterceptor.postHandle***
# log用时拦截器结束计时
[2024-01-17 08:17:56] [WARN ] [http-nio-8080-exec-2] [LogInterceptor.java:32][LogInterceptor.postHandle: Finished processing request at 2024-01-17T00:17:56.636557900Z - /students in 784 ms. Status code: 200]
***ResponsePostInterceptor.postHandle***# 拦截器组的 afterCompletion
***LogInterceptor.afterCompletion***
***ResponsePostInterceptor.afterCompletion***# 过滤器结束计时
***RequestHeaderCheckFilter.doFilter.end***
[2024-01-17 08:17:56] [WARN ] [http-nio-8080-exec-2] [LogFilter.java:31][LogFilter.doFilter: Finished processing request at 2024-01-17T00:17:56.920165800Z - /students in 1258 ms. Status code: 200]
***LogFilter.doFilter.end***

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/410964.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

行业分享----dbaplus174期:美团基于Orchestrator的MySQL高可用实践

记录 MySQL高可用方案-MMM、MHA、MGR、PXC https://blog.csdn.net/jycjyc/article/details/119731980 美团数据库高可用架构的演进与设想 https://tech.meituan.com/2017/06/29/database-availability-architecture.html

Apache Doris (六十四): Flink Doris Connector - (1)-源码编译

🏡 个人主页:IT贫道-CSDN博客 🚩 私聊博主:私聊博主加WX好友,获取更多资料哦~ 🔔 博主个人B栈地址:豹哥教你学编程的个人空间-豹哥教你学编程个人主页-哔哩哔哩视频 目录 1. Flink与Doris版本兼容

HarmonyOS—声明式UI描述

ArkTS以声明方式组合和扩展组件来描述应用程序的UI&#xff0c;同时还提供了基本的属性、事件和子组件配置方法&#xff0c;帮助开发者实现应用交互逻辑。 创建组件 根据组件构造方法的不同&#xff0c;创建组件包含有参数和无参数两种方式。 说明 创建组件时不需要new运算…

如何禁用WordPress站点的管理员电子邮件验证或修改检查频率?

今天boke112百科登录某个WordPress站点时&#xff0c;又出现“管理员邮件确认”的提示&#xff0c;要求确认此站点的管理员电子邮箱地址是否仍然正确。具体如下图所示&#xff1a; 如果点击“稍后提醒我”&#xff0c;那么管理员邮件验证页面就会在3天后重新显示。 说实话&…

多输入多输出 | Matlab实现PSO-CNN粒子群优化卷积神经网络多输入多输出预测

多输入多输出 | Matlab实现PSO-CNN粒子群优化卷积神经网络多输入多输出预测 目录 多输入多输出 | Matlab实现PSO-CNN粒子群优化卷积神经网络多输入多输出预测预测效果基本介绍模型背景程序设计参考资料 预测效果 基本介绍 Matlab实现PSO-CNN粒子群优化卷积神经网络多输入多输出…

WordPress后台仪表盘自定义添加删除概览项目插件Glance That

成功搭建WordPress站点&#xff0c;登录后台后可以在“仪表盘 – 概览”中看到包括多少篇文章、多少个页面、多少条评论和当前WordPress版本号及所使用的主题。具体如下图所示&#xff1a; 但是如果我们的WordPress站点还有自定义文章类型&#xff0c;也想在概览中显示出来应该…

【深度学习入门】深度学习基础概念与原理

*&#xff08;本篇文章旨在帮助新手了解深度学习的基础概念和原理&#xff0c;不深入讨论算法及核心公式&#xff09; 目录 一、深度学习概述 1、什么是深度学习&#xff1f; 2、深度学习与传统机器学习的区别 3、深度学习的应用领域 二、深度学习基本原理 1、神经网络的…

uniapp中uview组件库的NoticeBar 滚动通知 使用方法

目录 #平台差异说明 #基本使用 #配置主题 #配置图标 #配置滚动速度 #控制滚动的开始和暂停 #事件回调 #API #Props #Events 该组件用于滚动通告场景&#xff0c;有多种模式可供选择 #平台差异说明 AppH5微信小程序支付宝小程序百度小程序头条小程序QQ小程序√√√√…

如何避免知识付费小程序平台的陷阱?搭建平台的最佳实践

随着知识经济的兴起&#xff0c;知识付费已经成为一种趋势。越来越多的人开始将自己的知识和技能进行变现&#xff0c;而知识付费小程序平台则成为了一个重要的渠道。然而&#xff0c;市面上的知识付费小程序平台琳琅满目&#xff0c;其中不乏一些不良平台&#xff0c;让老实人…

阿赵UE学习笔记——10、Blender材质和绘制网格体

阿赵UE学习笔记目录   大家好&#xff0c;我是阿赵。   之前介绍了虚幻引擎的材质和材质实例。这次来介绍一个比较有趣的内置的Blender材质。   在用Unity的时候&#xff0c;我做过一个多通道混合地表贴图的效果&#xff0c;而要做过一个刷顶点颜色混合地表和水面的效果。…

【Web】CTFSHOW PHP特性刷题记录(全)

知其然知其所以然&#xff0c;尽量把每种特性都详细讲明白。 目录 web89 web90 web91 web92 web93 web94 web95 web96 web97 web98 web99 web100 web101 web102 web103 web104 web105 web106 web107 web108 web109 web110 web111 web112 web113 web…

nexus3 npm-hosted仓库迁移

迁移背景&#xff1a; 从nexus 3.33 升级到 nexus 3.64 过程中&#xff0c;私服 npm-hosted 无法上传。由于这个 npm-hosted 和 npm-proxy 放的同一个 blob存储&#xff0c;无法单独拆除去&#xff0c;所以采用迁移的方式 迁移思路&#xff1a; down下来 npm-hosted 仓库&am…