Spring Boot记录REST接口日志有Filter、HandlerInterceptor、AOP和ClientHttpRequestInterceptor四种主流方案:Filter最底层可捕获全量请求响应体但需包装缓存;Interceptor位于MVC层适合记录URL、参数、IP、状态码等,但难获取原始body;AOP灵活支持注解标记与日志入库;ClientHttpRequestInterceptor用于记录出站HTTP请求日志。

Spring Boot 中记录 REST 接口请求日志,核心目标是捕获 请求路径、方法、参数、IP、耗时、状态码、响应体(可选) 等关键信息。方式不止一种,选哪种取决于你的需求粒度、是否要记录请求体、是否需入库、是否已有统一拦截体系。下面介绍几种主流且实用的方案。
用 Filter 记录全链路请求/响应日志
Filter 是最底层、最通用的方式,能拿到原始 HttpServletRequest 和 HttpServletResponse,适合记录完整请求上下文(包括流式 body)。但要注意:request.getInputStream() 和 response.getOutputStream() 只能读一次,需用 ContentCachingRequestWrapper 和 ContentCachingResponseWrapper 包装。
- 继承
OncePerRequestFilter,避免异步或转发场景重复执行 - 在
doFilterInternal中包装 request/response,调用filterChain.doFilter()前后分别记录起始和结束信息 - 用
getContentAsByteArray()读取缓存的 body,转为字符串(注意编码和长度限制,敏感字段如密码需脱敏) - 耗时计算用
System.currentTimeMillis()差值,状态码从 response 获取
用 HandlerInterceptor 拦截 Controller 层调用
Interceptor 运行在 Spring MVC 生命周期中,比 Filter 更“上层”,天然支持获取 handler 方法、参数绑定结果,但拿不到原始 request body 流(除非提前解析并缓存)。
你接手一个需求时,是不是经常这样:"改一个小字段 → 结果把不相关的代码也改了"、"需求说得很模糊 → 做着做着发现跑偏了"、"数据库加个字段 → 上线才发现漏了数据兼容"、"做了个新功能 → 一个月后自己都忘了当时怎么设计的"、"写到一半被中断 → 再回来不知道从哪继续";这个 Skill 就是专门解决这些问题的。 它会自动探测你的项目环境(JDK、Spring Boot、ORM、数据库、前端框架),记在
- 实现
HandlerInterceptor,重写preHandle(记录 URL、method、query params、IP)和afterCompletion(记录 status、costTime、异常信息) - 可通过
RequestContextHolder获取当前 request,用ServletRequestAttributes提取参数 - 不推荐在
postHandle中记录响应体,因为ModelAndView对 @RestController 无效;响应体建议在afterCompletion阶段通过 response 输出流缓存获取(仍需包装)
用 AOP 切 Controller 方法执行过程
AOP 更灵活,适合按需标记(比如只对加了 @LogRequest 注解的方法记录),也便于与业务逻辑解耦、做日志入库等扩展。
- 定义自定义注解(如
@LogRequest),标注在 Controller 方法上 - 切面类用
@Around拦截,通过ProceedingJoinPoint获取方法签名、参数值 - 结合
RequestContextHolder补充 IP、URL、method 等信息 - 可将日志对象(如
RequestLog)存入数据库或发到消息队列,而非仅打到控制台 - 注意:AOP 拦不到全局异常处理器(
@RestControllerAdvice)处理的异常,需额外配合
给 RestTemplate 添加请求日志(调用方视角)
如果你的服务作为 HTTP 客户端调用第三方接口,也要记录出站请求日志,可用 ClientHttpRequestInterceptor。
- 实现
ClientHttpRequestInterceptor,在intercept中打印 request URI、method、headers、body - 执行
execution.execute()后,再读取ClientHttpResponse的 status、headers、body - 注册到
RestTemplate实例:通过setInterceptors或配置BeanPostProcessor - 注意 body 字节数组需指定编码(如 UTF-8),大响应体建议限长或开关控制

















