You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SpringBoot项目Interceptor层无法获取请求体的解决方法

SpringBoot拦截器获取请求体为空的解决方案

你的代码中无法获取请求体的核心原因有两个:

  1. ContentCachingRequestWrapper未被实际使用:你在preHandle中创建了包装类,但没有将其替换为后续处理流程使用的请求对象。Spring后续读取请求体时还是用的原始HttpServletRequest,包装类的缓存逻辑根本没触发。
  2. preHandle阶段请求体尚未被读取:HandlerInterceptor的preHandle执行时机早于Spring解析请求体的流程,此时请求体还未被读取,包装类自然没有缓存内容。

方案一:使用Filter实现(推荐)

Filter的执行时机早于DispatcherServlet,能在请求进入Spring MVC处理流程前完成请求体的包装与缓存,是最可靠的实现方式。

@Component
public class RequestBodyCachingFilter implements Filter {

    private static final Logger log = LoggerFactory.getLogger(RequestBodyCachingFilter.class);
    private final LogStore logStore;

    public RequestBodyCachingFilter(LogStore logStore) {
        this.logStore = logStore;
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        // 包装请求,后续所有流程都会使用这个包装类读取请求体
        ContentCachingRequestWrapper wrappedRequest = new ContentCachingRequestWrapper((HttpServletRequest) request);
        
        try {
            // 继续执行后续过滤链,此时Spring会读取包装类的请求体并触发缓存
            chain.doFilter(wrappedRequest, response);
            
            // 缓存已生成,直接获取请求体
            Log requestLog = new Log();
            requestLog.setPath(wrappedRequest.getRequestURI());
            requestLog.setMethod(wrappedRequest.getMethod());
            requestLog.setRequestObject(getRequestBody(wrappedRequest));
            
            logStore.save(requestLog);
        } finally {
            // 可选:清理资源,一般无需手动处理
        }
    }

    private String getRequestBody(ContentCachingRequestWrapper request) {
        byte[] buf = request.getContentAsByteArray();
        return buf.length > 0 ? new String(buf, StandardCharsets.UTF_8) : "";
    }
}

方案二:调整Interceptor实现(不推荐,仅作兼容参考)

如果必须使用Interceptor,需要先通过Filter包装请求,再在Interceptor中读取缓存:

步骤1:添加Filter包装请求

@Component
public class RequestWrapperFilter implements Filter {
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        ContentCachingRequestWrapper wrappedRequest = new ContentCachingRequestWrapper((HttpServletRequest) request);
        chain.doFilter(wrappedRequest, response);
    }
}

步骤2:在Interceptor的afterCompletion中读取缓存

此时请求体已被Spring读取,缓存内容可用:

@Component
public class CustomInterceptor implements HandlerInterceptor  {
    private static final Logger log = LoggerFactory.getLogger(CustomInterceptor.class);
    private final LogStore logStore;

    public CustomInterceptor(LogStore logStore) {
        this.logStore = logStore;
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        // 强制转换为包装类
        ContentCachingRequestWrapper wrappedRequest = (ContentCachingRequestWrapper) request;
        
        Log requestLog = new Log();
        requestLog.setPath(wrappedRequest.getRequestURI());
        requestLog.setMethod(wrappedRequest.getMethod());
        requestLog.setRequestObject(getRequestBody(wrappedRequest));
        
        logStore.save(requestLog);
    }

    private String getRequestBody(ContentCachingRequestWrapper request) {
        byte[] buf = request.getContentAsByteArray();
        return buf.length > 0 ? new String(buf, StandardCharsets.UTF_8) : "";
    }
}

内容的提问来源于stack exchange,提问作者Nghihoang

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 21:32:30