SpringBoot项目Interceptor层无法获取请求体的解决方法
SpringBoot拦截器获取请求体为空的解决方案
你的代码中无法获取请求体的核心原因有两个:
- ContentCachingRequestWrapper未被实际使用:你在
preHandle中创建了包装类,但没有将其替换为后续处理流程使用的请求对象。Spring后续读取请求体时还是用的原始HttpServletRequest,包装类的缓存逻辑根本没触发。 - 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
相关产品推荐
相关产品推荐

