一文吃透!Spring Boot 项目请求日志记录,这几招你绝对不能错过!
wptr33 2025-06-30 20:45 60 浏览
在互联网应用开发的高速赛道上,系统的稳定性、可维护性以及安全性是每一位开发者都必须关注的核心要素。而请求日志记录,就如同系统的 “黑匣子”,能够为我们提供排查故障、分析用户行为、优化系统性能等关键信息,在整个开发流程中占据着举足轻重的地位。对于广大 Spring Boot 开发者而言,如何快速、高效地实现请求日志记录,一直是日常开发工作中亟待解决的问题。
在过往的开发实践中,我们已经积累了一些常见的请求日志记录方式,它们各有特点,在不同的场景下发挥着重要作用。
一、传统的请求日志记录方式
1、使用拦截器
拦截器就像是一位忠诚的 “门卫”,在请求进入控制器之前和请求完成之后,都能执行特定的操作。
大致流程
- 创建一个自定义的拦截器类,让它实现 Spring 框架提供的 HandlerInterceptor 接口,从而具备拦截请求的能力。
- 重写 preHandle 方法,这个方法会在请求到达控制器之前被调用,我们可以在这个方法中记录请求的关键信息,比如请求的 URL、参数等,为后续的分析和排查提供依据。
- 重写 afterCompletion 方法,在请求处理完成之后,这个方法会被触发,我们可以在这里记录请求的处理结果、耗时等信息,全面了解请求的生命周期。
- 最后,将我们创建的拦截器注册到 Spring MVC 的配置中,这样拦截器就能在整个项目中发挥作用了。
2、使用过滤器
过滤器类似于一个 “关卡”,对所有经过的请求和响应进行统一的处理。
大致流程
- 创建一个自定义的过滤器类,实现 Filter 接口,使其能够对请求和响应进行过滤操作。
- 在 doFilter 方法中,编写记录请求和响应日志的逻辑,这个方法会在请求和响应的处理过程中被调用,我们可以在这里获取并记录请求的详细信息,包括请求头、请求体等。
- 将过滤器注册到 Servlet 容器中,确保它能够对所有的请求和响应生效。
3、使用AOP
AOP(面向切面编程)就像是一把 “手术刀”,能够精准地切入到方法的执行过程中,实现对日志记录的统一管理。
大致流程
- 定义一个切面类,使用 @Aspect 注解将其标记为切面,表明这个类将用于处理横切关注点。
- 使用 @Around 注解定义切点,切点就像是一个 “钩子”,可以在方法执行前、执行后或抛出异常后,执行我们定义的日志记录逻辑,灵活地记录不同阶段的信息。
- 将切面类注册到 Spring 容器中,使其能够在项目中发挥作用。
这些传统的方式虽然有效,但在实际应用中可能会面临一些配置繁琐、代码冗余等问题。那么,有没有更简单、高效的方法呢?答案是肯定的!Spring Boot 2 为我们提供了一些内置的超强请求记录方法,让我们一起来看看吧!
二、Spring Boot 2 内置的超便捷请求记录方法
方法一:通过 Spring Boot Actuator 的 httptrace 端点
步骤如下:
1、项目pom引入Actuator GAV
在项目的 pom 文件中添加以下依赖,引入 Spring Boot Actuator:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
2、开启httptrace端点
在配置文件中,我们可以通过以下配置开启所有端点,以便使用 httptrace 端点:
management:
endpoints:
web:
exposure:
include: '*'
3、测试
编写一个测试 controller,用于模拟请求:
@RequestMapping("echo")
@RestController
public class EchoController {
@RequestMapping("say/{sleep}")
public String echo(@PathVariable("sleep") long sleep, String msg) {
if(sleep == 0){
throw new IllegalArgumentException("sleep参数不能为0");
}
try {
TimeUnit.MILLISECONDS.sleep(sleep);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
return "echo:" + msg;
}
}
浏览器先访问测试控制器
http://localhost:8080/echo/say/100?msg=hello
再访问下httptrace端点
http://localhost:8080/actuator/httptrace
这时,你会惊喜地发现,请求记录已经清晰地呈现在你面前。不过,需要注意的是,httptrace 信息默认存储在内存中,如果需要持久化存储,可以通过实现
org.springframework.boot.actuate.trace.http.HttpTraceRepository
,将其存储到其他存储介质上,如数据库、文件系统等。
方法二:通过监听 ServletRequestHandledEvent 事件
Spring 框架提供了丰富的事件机制,我们可以通过监听
ServletRequestHandledEvent 事件来记录请求日志。
示例代码如下:
@Slf4j
public class RequestLogEventListener {
@EventListener
public void listener(ServletRequestHandledEvent event){
log.info("request client ip :{},request method:{}",event.getClientAddress(),event.getMethod());
log.info("request url:{},cost time:{} ms",event.getRequestUrl(),event.getProcessingTimeMillis());
if(event.wasFailure()){
log.error("request fail,error msg:{}",event.getFailureCause());
}
}
}
访问测试控制器,然后观察控制台
你会发现请求日志已经被准确地记录下来。
ServletRequestHandledEvent 事件由
org.springframework.web.servlet.FrameworkServlet#processRequest
方法触发发送的,这为我们提供了一个非常方便的记录请求日志的时机。
开启 DispatcherServlet 日志,日志级别为debug
通过开启 DispatcherServlet 的日志,我们可以获取到详细的请求信息。
在配置文件中进行如下配置:
logging:
level:
org.springframework.web.servlet.DispatcherServlet: DEBUG
可以通过
http://localhost:8080/actuator/loggers/org.springframework.web.servlet.DispatcherServlet 动态调整日志级别,不过需要注意的是,这种方式在项目重启后,日志级别会恢复默认。示例命令如下:
curl -X POST http://localhost:8080/actuator/loggers/org.springframework.web.servlet.DispatcherServlet \
-H "Content-Type: application/json" \
-d '{"configuredLevel": "DEBUG"}'
最后访问测试控制器,观察控制台
你会发现有请求信息输出。但细心的你可能会发现 parameters={masked},这是因为 DispatcherServlet 默认会将请求参数进行掩码处理,以保护敏感信息不被泄露。不过,我们可以通过以下配置让请求参数显示出来:
spring:
http:
log-request-details: true
将请求参数也显示出来,再次访问测试控制器,观察控制台
会发现请求参数已经打印出来
三、总结
本文详细介绍了 Spring Boot 内置的三种记录请求日志的方式,这些方法不仅简单易用,而且功能强大,大大提高了我们的开发效率。如果想要将日志记录到存储介质,个人比较推荐使用
ServletRequestHandledEvent 这种方式,它的配置相对简单,并且能够满足大多数场景的需求。当然,如果有定制化的需求,比如需要记录响应体,那么开头介绍的那三种传统方式也是不错的选择,它们能够提供更灵活的扩展能力。但无论如何,利用好 Spring Boot 提供的这些内置功能,能够让我们的开发工作事半功倍。
四、demo链接
为了方便大家实践,文中所有代码的 demo 链接为:
https://github.com/lyb-geek/springboot-learning/tree/master/springboot-request-log。
赶紧动手实践一下吧,相信你一定会对 Spring Boot 的请求日志记录有更深入的理解!
希望这篇文章能够帮助你在 Spring Boot 开发中更好地记录请求日志,提升系统的可维护性和稳定性。如果在实践过程中有任何问题,欢迎随时交流探讨!
相关推荐
- 什么是Java中的继承?如何实现继承?
-
什么是继承?...
- Java 继承与多态:从基础到实战的深度解析
-
在面向对象编程(OOP)的三大支柱中,继承与多态是构建灵活、可复用代码的核心。无论是日常开发还是框架设计,这两个概念都扮演着至关重要的角色。本文将从基础概念出发,结合实例与图解,带你彻底搞懂Java...
- Java基础教程:Java继承概述_java的继承
-
继承概述假如我们要定义如下类:学生类,老师类和工人类,分析如下。学生类属性:姓名,年龄行为:吃饭,睡觉老师类属性:姓名,年龄,薪水行为:吃饭,睡觉,教书班主任属性:姓名,年龄,薪水行为:吃饭,睡觉,管...
- java4个技巧:从继承和覆盖,到最终的类和方法
-
日复一日,我们编写的大多数Java只使用了该语言全套功能的一小部分。我们实例化的每个流以及我们在实例变量前面加上的每个@Autowired注解都足以完成我们的大部分目标。然而,有些时候,我们必须求助于...
- java:举例说明继承的概念_java继承的理解
-
在现实生活中,继承一般指的是子女继承父辈的财产。在程序中,继承描述的是事物之间的所属关系,通过继承可以使多种事物之间形成一种关系体系。例如猫和狗都属于动物,程序中便可以描述为猫和狗继承自动物,同理,...
- 从零开始构建一款开源的 Vibe Coding 产品 Week1Day4:业界调研之 Agent 横向对比
-
前情回顾前面两天我们重点调研了了一下Cursor的原理和Cursor中一个关键的工具edit_file的实现,但是其他CodingAgent也需要稍微摸一下底,看看有没有优秀之处,下...
- 学会这几个插件,让你的Notepad++使用起来更丝滑
-
搞程序开发的小伙伴相信对Notepad++都不会陌生,是一个占用空间少、打开启动快的文件编辑器,很多程序员喜欢使用Notepad++进行纯文本编辑或者脚本开发,但是Notepad++的功能绝不止于此,...
- 将 node_modules 目录放入 Git 仓库的优点
-
推荐一篇文章Whyyoushouldcheck-inyournodedependencies[1]...
- 再度加码AI编程,腾讯发布AI CLI并宣布CodeBuddy IDE开启公测
-
“再熬一年,90%的程序员可能再也用不着写for循环。”凌晨两点半,王工还在公司敲键盘。他手里那份需求文档写了足足六页,产品经理反复改了三次。放在过去,光数据库建表、接口对接、单元测试就得写两三天。现...
- git 如何查看stash的内容_git查看ssh key
-
1.查看Stash列表首先,使用gitstashlist查看所有已保存的stash:...
- 6万星+ Git命令懒人必备!lazygit 终端UI神器,效率翻倍超顺手!
-
项目概览lazygit是一个基于终端的Git命令可视化工具,通过简易的TUI(文本用户界面)提升Git操作效率。开发者无需记忆复杂命令,即可完成分支管理、提交、合并等操作。...
- 《Gemini CLI 实战系列》(一)Gemini CLI 入门:AI 上命令行的第一步
-
谷歌的Gemini模型最近热度很高,而它的...
- deepin IDE新版发布:支持玲珑构建、增强AI智能化
-
IT之家8月7日消息,深度操作系统官方公众号昨日(8月6日)发布博文,更新推出新版deepin集成开发环境(IDE),重点支持玲珑构建。支持玲珑构建deepinIDE在本次重磅更...
- 狂揽82.7k的star,这款开源可视化神器,轻松创建流程图和图表
-
再不用Mermaid,你的技术文档可能已经在悄悄“腐烂”——图表版本对不上、同事改完没同步、评审会上被一句“这图哪来的”问得哑口无言。这不是危言耸听。GitHub2025年开发者报告显示,63%的新仓...
- 《Gemini CLI 实战系列》(五)打造专属命令行工具箱
-
在前几篇文章中,我们介绍了GeminiCLI的基础用法、效率提升、文件处理和与外部工具结合。今天我们进入第五篇...
- 一周热门
-
-
C# 13 和 .NET 9 全知道 :13 使用 ASP.NET Core 构建网站 (1)
-
程序员的开源月刊《HelloGitHub》第 71 期
-
详细介绍一下Redis的Watch机制,可以利用Watch机制来做什么?
-
如何将AI助手接入微信(打开ai手机助手)
-
SparkSQL——DataFrame的创建与使用
-
假如有100W个用户抢一张票,除了负载均衡办法,怎么支持高并发?
-
Java面试必考问题:什么是乐观锁与悲观锁
-
redission YYDS spring boot redission 使用
-
一文带你了解Redis与Memcached? redis与memcached的区别
-
如何利用Redis进行事务处理呢? 如何利用redis进行事务处理呢英文
-
- 最近发表
-
- 什么是Java中的继承?如何实现继承?
- Java 继承与多态:从基础到实战的深度解析
- Java基础教程:Java继承概述_java的继承
- java4个技巧:从继承和覆盖,到最终的类和方法
- java:举例说明继承的概念_java继承的理解
- 从零开始构建一款开源的 Vibe Coding 产品 Week1Day4:业界调研之 Agent 横向对比
- 学会这几个插件,让你的Notepad++使用起来更丝滑
- 将 node_modules 目录放入 Git 仓库的优点
- 再度加码AI编程,腾讯发布AI CLI并宣布CodeBuddy IDE开启公测
- git 如何查看stash的内容_git查看ssh key
- 标签列表
-
- git pull (33)
- git fetch (35)
- mysql insert (35)
- mysql distinct (37)
- concat_ws (36)
- java continue (36)
- jenkins官网 (37)
- mysql 子查询 (37)
- python元组 (33)
- mybatis 分页 (35)
- vba split (37)
- redis watch (34)
- python list sort (37)
- nvarchar2 (34)
- mysql not null (36)
- hmset (35)
- python telnet (35)
- python readlines() 方法 (36)
- munmap (35)
- docker network create (35)
- redis 集合 (37)
- python sftp (37)
- setpriority (34)
- c语言 switch (34)
- git commit (34)