统计请求的处理时间(用时)既可以使用 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 { @Override public 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 { @Bean public FilterRegistrationBeantokenFilterRegistration() { FilterRegistrationBean 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 { @Override public 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; } @Override public 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); } } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { System.err.println("***LogInterceptor.afterCompletion***"); // 在此可以添加额外的后处理逻辑,但本例中我们不需要 } }
注册拦截器(Interceptor)
@Configuration public class WebMvcConfig implements WebMvcConfigurer { @Autowired private ResponsePostInterceptor responsePostInterceptor; @Autowired private LogInterceptor logInterceptor; /** * 为拦截器注册表添加拦截器 * * @param registry 拦截器注册表 */ @Override public 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***
猜你喜欢
- 12天前(上海文旅产业发展高峰论坛)《上海打造文旅元宇宙新赛道行动方案》发布
- 12天前(哈弗h9优惠9万是真的吗)热浪来袭,哈弗H9超值补贴火热加码
- 12天前(三亚太阳湾柏悦度假酒店)三亚太阳湾柏悦酒店携手ROSEONLY诺誓缔造浪漫七夕
- 12天前(“为人民绽放——国家艺术基金优秀剧目展演”在合肥开幕)“为人民绽放——国家艺术基金优秀剧目展演”在合肥开幕
- 12天前(曼谷丽思卡尔顿公寓价格)曼谷丽思卡尔顿酒店盛大启幕,开创泰国奢华雅致新纪元
- 12天前(马尔代夫华尔道夫酒店多少钱)Chef Zhao就任马尔代夫伊挞富士岛华尔道夫酒店Li Long中餐厅新主厨
- 12天前(岭南东方大酒店)粤西成势 | 阳江阳春长兴岭南东方酒店正式签约,粤西文旅再添明珠
- 12天前(美诺酒店集团旗下臻选品牌m collection)美诺酒店集团启动盛橡品牌战略焕新 开启全球扩张新篇章
- 12天前(冬日生活还没安排?上抖音一键打包北方花式过冬精彩)冬日生活还没安排?上抖音一键打包北方花式过冬精彩
- 12天前(阿斯塔纳航空属于哪个联盟)阿斯塔纳航空荣获Skytrax世界航空公司大奖,将继续助力中哈交流往来
网友评论
- 搜索
- 最新文章
- (2020广州车展哈弗)你的猛龙 独一无二 哈弗猛龙广州车展闪耀登场
- (哈弗新能源suv2019款)智能科技颠覆出行体验 哈弗重塑新能源越野SUV价值认知
- (2021款全新哈弗h5自动四驱报价)新哈弗H5再赴保障之旅,无惧冰雪护航哈弗全民电四驱挑战赛
- (海南航空现况怎样)用一场直播找到市场扩张新渠道,海南航空做对了什么?
- (visa jcb 日本)优惠面面俱到 JCB信用卡邀您畅玩日本冰雪季
- (第三届“堡里有年味·回村过大年”民俗花灯会活动)第三届“堡里有年味·回村过大年”民俗花灯会活动
- (展示非遗魅力 长安启源助力铜梁龙舞出征)展示非遗魅力 长安启源助力铜梁龙舞出征
- (阿斯塔纳航空公司)阿斯塔纳航空机队飞机数量增至50架
- (北京香港航班动态查询)香港快运航空北京大兴新航线今日首航
- (我在港航“呵护”飞机 每一次安全着陆就是最好的荣誉)我在港航“呵护”飞机 每一次安全着陆就是最好的荣誉
- 热门文章