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

Spring Boot 2.1.4拦截器中如何获取RequestEntity实例

在Spring Boot Interceptor的preHandle中获取RequestEntity的解决方案

首先得明确为什么你之前的尝试都失败了:

  • @Autowired注入RequestEntity行不通:RequestEntity是Spring MVC针对每个请求临时创建的请求域对象,并不是Spring容器管理的单例Bean,所以依赖注入根本找不到对应的实例,自然会空指针。
  • Controller方法添加RequestEntity参数也无法在preHandle中获取:Spring MVC会在调用Controller方法之前,通过HandlerMethodArgumentResolver解析参数并创建RequestEntity,但这个步骤是在Interceptor的preHandle执行之后才发生的,所以preHandle阶段这个对象还没生成。

接下来给你两种可行的解决方案:

方案一:手动从HttpServletRequest构建RequestEntity

RequestEntity本质就是对请求方法、URL、请求头、请求体的封装,我们可以直接从HttpServletRequest中提取这些信息手动构建,而且为了避免请求体只能读取一次的问题,需要用ContentCachingRequestWrapper包装请求:

@Override
public boolean preHandle(HttpServletRequest requestServlet, HttpServletResponse responseServlet, Object handler) throws Exception {
    // 包装请求,支持重复读取请求体
    ContentCachingRequestWrapper request = new ContentCachingRequestWrapper(requestServlet);
    
    // 1. 获取请求方法
    HttpMethod method = HttpMethod.valueOf(request.getMethod());
    // 2. 获取请求URI
    URI uri = URI.create(request.getRequestURL().toString());
    // 3. 构建请求头
    HttpHeaders headers = new HttpHeaders();
    Enumeration<String> headerNames = request.getHeaderNames();
    while (headerNames.hasMoreElements()) {
        String headerName = headerNames.nextElement();
        headers.add(headerName, request.getHeader(headerName));
    }
    // 4. 获取请求体(这里以String为例,根据你的需求调整类型)
    byte[] bodyBytes = request.getContentAsByteArray();
    String body = new String(bodyBytes, request.getCharacterEncoding());
    
    // 5. 构建RequestEntity实例
    RequestEntity<String> requestEntity = new RequestEntity<>(body, headers, method, uri);
    
    // 现在就可以正常使用requestEntity了
    System.out.println(requestEntity.getHeaders());
    return true;
}

这个方案的优势是不依赖Controller的方法参数,不管你的Controller有没有声明RequestEntity参数,都能在preHandle中获取到。

方案二:自定义参数解析器缓存RequestEntity(仅适用于Controller声明了RequestEntity参数的场景)

如果你的Controller方法必然会声明RequestEntity参数,可以自定义一个HandlerMethodArgumentResolver,在解析出RequestEntity后把它存入请求属性中,后续在Interceptor的postHandle中获取(注意:preHandle阶段还是拿不到,因为参数解析在preHandle之后):

  1. 自定义参数解析器:
public class CachingRequestEntityArgumentResolver extends RequestEntityMethodArgumentResolver {

    public CachingRequestEntityArgumentResolver(List<HttpMessageConverter<?>> converters) {
        super(converters);
    }

    @Override
    public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
        RequestEntity<?> requestEntity = (RequestEntity<?>) super.resolveArgument(parameter, mavContainer, webRequest, binderFactory);
        // 存入请求属性
        webRequest.setAttribute("REQUEST_ENTITY", requestEntity, NativeWebRequest.SCOPE_REQUEST);
        return requestEntity;
    }
}
  1. 注册这个解析器:
@Configuration
public class WebConfig implements WebMvcConfigurer {
    @Autowired
    private List<HttpMessageConverter<?>> messageConverters;

    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
        resolvers.add(new CachingRequestEntityArgumentResolver(messageConverters));
    }
}
  1. 在Interceptor的postHandle中获取:
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
    RequestEntity<?> requestEntity = (RequestEntity<?>) request.getAttribute("REQUEST_ENTITY");
    if (requestEntity != null) {
        System.out.println(requestEntity.getHeaders());
    }
}

不过这个方案只能在postHandle中获取,如果你必须在preHandle中拿到,方案一是更合适的选择。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 05:32:26