百度360必应搜狗淘宝本站头条
当前位置:网站首页 > IT技术 > 正文

一文吃透!Spring Boot 项目请求日志记录,这几招你绝对不能错过!

wptr33 2025-06-30 20:45 3 浏览

在互联网应用开发的高速赛道上,系统的稳定性、可维护性以及安全性是每一位开发者都必须关注的核心要素。而请求日志记录,就如同系统的 “黑匣子”,能够为我们提供排查故障、分析用户行为、优化系统性能等关键信息,在整个开发流程中占据着举足轻重的地位。对于广大 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 开发中更好地记录请求日志,提升系统的可维护性和稳定性。如果在实践过程中有任何问题,欢迎随时交流探讨!

相关推荐

SpringBoot 3 + Flutter3 实战低代码运营管理-10章

获课》aixuetang.xyz/5075/三天构建运营管理系统:SpringBoot3+Flutter3高效开发方法论...

SpringBoot探针实现:从零构建应用健康监控利器

SpringBoot探针实现:从零构建应用健康监控利器声明本文中的所有案例代码、配置仅供参考,如需使用请严格做好相关测试及评估,对于因参照本文内容进行操作而导致的任何直接或间接损失,作者概不负责。本文...

Spring Batch中的JobRepository:批处理的“记忆大师”是如何工作

一、JobRepository是谁?——批处理的“档案馆”JobRepository是SpringBatch的“记忆中枢”,负责记录所有Job和Step的执行状态。它像一位严谨的档案管理员,把任务执...

Github霸榜的SpringBoot全套学习教程,从入门到实战,内容超详细

前言...

还在为 Spring Boot3 技术整合发愁?一文解锁大厂都在用的实用方案

你在使用SpringBoot3开发后端项目时,是不是常常陷入这样的困境?想提升项目性能和功能,却不知道该整合哪些技术;好不容易选定技术,又在配置和使用上频频踩坑。其实,这是很多互联网大厂后端开发...

一文吃透!Spring Boot 项目请求日志记录,这几招你绝对不能错过!

在互联网应用开发的高速赛道上,系统的稳定性、可维护性以及安全性是每一位开发者都必须关注的核心要素。而请求日志记录,就如同系统的“黑匣子”,能够为我们提供排查故障、分析用户行为、优化系统性能等关键信息...

spring-boot-starter-actuator简单介绍

SpringBootActuator是SpringBoot的一个功能强大的子项目,它提供了一些有用的监控和管理SpringBoot应用程序的端点。SpringBootActuat...

使用SpringBoot钩子或Actuator实现优雅停机

服务如何响应停机信号在java中我们可以直接利用通过Runtime...

28-自定义Spring Boot Actuator指标

上篇我们学习了《27-自定义SpringBootActuator健康指示器》,本篇我们学习自定义SpringBootActuator指标(Metric)。...

如何在Spring Boot中整合Spring Boot Actuator进行服务应用监控?

监控是确保系统稳定性和性能的关键组成部分,而在SpringBoot中就提供了默认的应用监控方案SpringBootActuator,通过SpringBootActuator提供了开箱即用的应...

「Spring Boot」 Actuator Endpoint

Actuator官网地址:https://docs.spring.io/spring-boot/docs/2.5.6/reference/html/actuator.html目的监控并管理应用程序...

Spring Boot Actuator监控功能全面剖析

SpringBootActuator监控功能全面剖析在现代企业级Java开发中,SpringBoot以其轻量化、高效率的特性深受开发者青睐。而作为SpringBoot生态系统的重要组成部分,S...

1000字彻底搞懂SpringBootActuator组件!

SpringBootActuator组件SpringBootActuator通过HTTPendpoints或者JMX来管理和监控SpringBoot应用,如服务的审计、健康检查、指标统计和...

JavaScript数据类型(javascript数据类型介绍)

基本数据类型BooleanNullNumberStringSymbolUndefined对象数据类型ObjectArray定义:JavaScript数组是内置的对象之一,它可以用一个变量来存储多个同种...

能运行,不代表它是对的:5 个潜伏在正常功能下的 JavaScript 错误

JavaScript的动态性和复杂性意味着,代码虽然表面上正常运行,但一些深层次、隐蔽的陷阱往往让人意想不到,梳理了几个JavaScript开发中难以发现的隐蔽错误,旨在帮助我们写出更健壮、更可...