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

Spring Boot实现@RequestScope请求域Bean时过滤器抛出空指针问题

问题根因

你用@RequestScope + CGLIB代理实现请求域共享Bean的整体思路是完全正确的,空指针的触发原因是自定义Filter的执行时机早于Spring请求上下文的初始化节点:

  • 加了@Component的Filter会被Servlet容器直接注册,执行优先级远早于Spring用于初始化请求上下文的RequestContextFilter
  • 此时请求域代理对象内部还没有绑定当前请求的实际实例,调用setAppInfo方法时会因访问空实例触发NPE。

你代码中还存在几处拼写/语法错误,需同步修正:

  • 类定义错误:public Class RequestHeaderInfo 应为 public class RequestHeaderInfo
  • Servlet类名错误:HTTPServletRequest 应为 HttpServletRequest
  • Controller注解错误:@Contoller 应为 @Controller
可行解决方案

方案1:调整Filter的注册逻辑,对齐执行时机

  • 移除RequestFilter上的@Component注解,避免被Servlet容器默认自动注册
  • 改用FilterRegistrationBean手动注册Filter,设置执行顺序晚于Spring请求上下文初始化节点,同时将Spring容器管理的请求域代理对象传入Filter,避免依赖注入失效
    代码示例:
// 移除原有@Component注解
public class RequestFilter implements Filter {
    private final RequestHeaderInfo requestHeaderInfo;

    public RequestFilter(RequestHeaderInfo requestHeaderInfo) {
        this.requestHeaderInfo = requestHeaderInfo;
    }

    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) req;
        requestHeaderInfo.setAppInfo(request.getHeader("appInfo"));
        chain.doFilter(req, res);
    }
}

对应配置类:

@Configuration
public class WebConfig {
    @Bean
    public FilterRegistrationBean<RequestFilter> registerRequestFilter(RequestHeaderInfo requestHeaderInfo) {
        FilterRegistrationBean<RequestFilter> registration = new FilterRegistrationBean<>();
        registration.setFilter(new RequestFilter(requestHeaderInfo));
        // 优先级设置为在Spring RequestContextFilter之后执行
        registration.setOrder(Ordered.HIGHEST_PRECEDENCE + 1);
        registration.addUrlPatterns("/*");
        return registration;
    }
}

方案2:更可靠的替代实现——用HandlerInterceptor做请求头解析

Filter属于Servlet容器层面组件,不直接对接Spring MVC生命周期,如果仅需处理MVC链路内的请求头,用拦截器实现的可靠性更高:此时请求上下文已完全初始化,请求域Bean可正常读写,无需手动调整Filter执行顺序。

  • 实现HandlerInterceptor接口,在preHandle方法中完成请求头解析与属性设置
  • 实现WebMvcConfigurer接口,将自定义拦截器注册到MVC链路中

注意:所有请求域Bean必须配置proxyMode = ScopedProxyMode.TARGET_CLASS,否则会因请求域生命周期与单例Bean生命周期不匹配,出现注入异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.27 10:54:06