
Spring 内置的 CommonsRequestLoggingFilter 默认以 DEBUG 级别输出请求日志,但可通过继承并重写其逻辑,改用 INFO 或其他任意级别记录,无需修改 Spring 源码或依赖日志框架的底层拦截。
spring 内置的 `commonsrequestloggingfilter` 默认以 debug 级别输出请求日志,但可通过继承并重写其逻辑,改用 info 或其他任意级别记录,无需修改 spring 源码或依赖日志框架的底层拦截。
在 Spring Boot 应用中,若仅通过 logging.level.org.springframework.web.filter.CommonsRequestLoggingFilter=DEBUG 配置日志级别,无法将其降级为 INFO——因为该 Filter 内部硬编码使用 logger.debug(...),日志级别由调用方决定,而非由 Logger 实例的配置级别动态控制。
解决思路是:不依赖原生 Filter 的日志行为,而是创建一个功能等效但日志级别可自定义的子类。推荐做法是继承 CommonsRequestLoggingFilter,重写 doFilterInternal 方法,在其中使用你指定级别的日志语句(如 logger.info(...)),再显式调用父类逻辑完成原始功能(如请求体截断、参数记录等)。
以下是一个生产就绪的示例:
@Order(Ordered.HIGHEST_PRECEDENCE)
public class CustomRequestLoggingFilter extends CommonsRequestLoggingFilter {
private static final Logger logger = LoggerFactory.getLogger(CustomRequestLoggingFilter.class);
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
FilterChain filterChain) throws ServletException, IOException {
// ✅ 使用 INFO 级别输出关键请求信息(可按需扩展:IP、耗时、Header 等)
logger.info("HTTP {} {} [{}]",
request.getMethod(),
request.getRequestURI(),
Optional.ofNullable(request.getRemoteAddr()).orElse("unknown"));
// ✅ 保留父类原有逻辑(如启用 includeQueryString、includePayload 等配置)
super.doFilterInternal(request, response, filterChain);
}
}
接着,通过 FilterRegistrationBean 将其注册为 Spring Bean,并确保优先级最高(HIGHEST_PRECEDENCE),以保障在请求被其他过滤器(如安全过滤器、字符编码过滤器)修改前完成日志记录:
@Configuration
public class WebConfig {
@Bean
public FilterRegistrationBean<customrequestloggingfilter> customRequestLoggingFilter() {
FilterRegistrationBean<customrequestloggingfilter> registration = new FilterRegistrationBean();
registration.setFilter(new CustomRequestLoggingFilter());
registration.setOrder(Ordered.HIGHEST_PRECEDENCE);
registration.addUrlPatterns("/*"); // 覆盖全部请求路径
return registration;
}
}</customrequestloggingfilter></customrequestloggingfilter>
⚠️ 注意事项:
- 不要同时启用原生
CommonsRequestLoggingFilter(如通过spring.web.log-request-details=true或手动注册),否则将产生重复日志; - 若需记录请求体(payload)或查询参数,需在
CustomRequestLoggingFilter构造后调用setIncludeQueryString(true)、setIncludePayload(true)等方法(注意 payload 记录可能影响性能和内存); - 日志内容应避免敏感字段(如
Authorization、Cookie、密码类参数),建议结合SensitiveDataFilter或自定义脱敏逻辑; - 如需结构化日志(如 JSON 格式),可搭配 Logback 的
JsonLayout或 Log4j2 的JacksonJsonLayout,并在logger.info()中传入结构化 Map 对象。
通过该方案,你完全掌控日志级别、格式与时机,既保持了 Spring 请求日志的核心能力,又解耦了日志级别与框架实现的强绑定。










