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

SpringBoot从2.7.2升级到3.2.0后Filter抛出非空异常排查

SpringBoot 2.7.2升级至3.2.0启动Tomcat抛出Filter must not be null异常解决

升级SpringBoot版本从2.7.2到3.2.0后,启动嵌入式Tomcat时出现以下异常:

Caused by: org.springframework.boot.web.server.WebServerException:
Unable to start embedded Tomcat at
org.springframework.boot.web.embedded.tomcat.TomcatWebServer.initialize(TomcatWebServer.java:142)
at
org.springframework.boot.web.embedded.tomcat.TomcatWebServer.(TomcatWebServer.java:104)
at
org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory.getTomcatWebServer(TomcatServletWebServerFactory.java:501)
at
org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory.getWebServer(TomcatServletWebServerFactory.java:218)
at
org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.createWebServer(ServletWebServerApplicationContext.java:188)
at
org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.onRefresh(ServletWebServerApplicationContext.java:162)
... 11 common frames omitted Caused by:
java.lang.IllegalArgumentException: Filter must not be null at
org.springframework.util.Assert.notNull(Assert.java:172) at
org.springframework.boot.web.servlet.AbstractFilterRegistrationBean.getDescription(AbstractFilterRegistrationBean.java:223)
at
org.springframework.boot.web.servlet.RegistrationBean.onStartup(RegistrationBean.java:47)
at
org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.selfInitialize(ServletWebServerApplicationContext.java:241)
at
org.springframework.boot.web.embedded.tomcat.TomcatStarter.onStartup(TomcatStarter.java:52)
at
org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:4850)
at
org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:171)
at
org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1332)
at
org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1322)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
at
org.apache.tomcat.util.threads.InlineExecutorService.execute(InlineExecutorService.java:75)
at
java.base/java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:145)
at
org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:866)
at
org.apache.catalina.core.StandardHost.startInternal(StandardHost.java:845)
at
org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:171)
at
org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1332)
at
org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1322)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
at
org.apache.tomcat.util.threads.InlineExecutorService.execute(InlineExecutorService.java:75)
at
java.base/java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:145)
at
org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:866)
at
org.apache.catalina.core.StandardEngine.startInternal(StandardEngine.java:240)
at
org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:171)
at
org.apache.catalina.core.StandardService.startInternal(StandardService.java:433)
at
org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:171)
at
org.apache.catalina.core.StandardServer.startInternal(StandardServer.java:917)
at
org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:171)
at org.apache.catalina.startup.Tomcat.start(Tomcat.java:488) at
org.springframework.boot.web.embedded.tomcat.TomcatWebServer.initialize(TomcatWebServer.java:123)
... 16 common frames omitted

涉及的配置类代码如下:

@Configuration
public class WebMvcConfig implements  WebMvcConfigurer  {

    @Value("${system.debug.enabled:false}")
    private boolean debugEnabled;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(httpHeaderInterceptor());
    }

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/log/**").allowedOrigins("*")
                .allowedMethods("POST", "GET", "PUT", "PATCH", "OPTIONS", "DELETE")
                .allowedHeaders("header1", "header2", "header3")
                .allowedHeaders("Origin", "Authorization", "X-Requested-With", "Content-Type", "Accept")
                .allowCredentials(false).maxAge(3600);
    }

    @Bean
    public HandlerInterceptor httpHeaderInterceptor() {
        return (HandlerInterceptor) new HttpHeaderInterceptor();
    }
     
    private FilterRegistrationBean newFilterRegistrationBean(Filter filter, int order) {
        final FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
        filterRegistrationBean.setOrder(order);
        filterRegistrationBean.addUrlPatterns("/*");
        return filterRegistrationBean;
    }

    @Bean
    public FilterRegistrationBean stopWatchFilter() {
        Filter filter = debugEnabled ? new StopWatchFilter() : new NoopFilter();
        FilterRegistrationBean filterRegistrationBean = newFilterRegistrationBean(filter, 1);
        return filterRegistrationBean;
    }

    @Bean
    public FilterRegistrationBean gzipFilter() {
        GZipRequestFilter gzipRequestFilter = new GZipRequestFilter();
        return newFilterRegistrationBean(gzipRequestFilter, 2);
    }

    @Bean
    public FilterRegistrationBean registerOpenSessionInViewFilterBean() {
        OpenEntityManagerInViewFilter openEntityManagerInViewFilter = new OpenEntityManagerInViewFilter();
        return newFilterRegistrationBean(openEntityManagerInViewFilter, 1);
    }
}

经排查,异常由gzipFilter和registerOpenSessionInViewFilterBean这两个Filter注册方法引发——虽然初始化了Filter实例,但启动时仍提示Filter为null,移除该部分代码后服务器可正常启动。

问题原因

核心问题出在newFilterRegistrationBean方法中:该方法接收了Filter实例,但没有将Filter赋值给FilterRegistrationBean。SpringBoot 3.x版本对FilterRegistrationBean的校验逻辑比2.7.x更严格,启动时会直接断言Filter不能为null,而未赋值的FilterRegistrationBean内部Filter属性默认是null,因此触发异常。

解决方案

修改newFilterRegistrationBean方法,将传入的Filter实例设置到FilterRegistrationBean中,有两种实现方式:

方式一:使用带Filter参数的构造器

private FilterRegistrationBean newFilterRegistrationBean(Filter filter, int order) {
    final FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(filter);
    filterRegistrationBean.setOrder(order);
    filterRegistrationBean.addUrlPatterns("/*");
    return filterRegistrationBean;
}

方式二:调用setFilter方法赋值

private FilterRegistrationBean newFilterRegistrationBean(Filter filter, int order) {
    final FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
    filterRegistrationBean.setFilter(filter); // 新增该行,设置Filter实例
    filterRegistrationBean.setOrder(order);
    filterRegistrationBean.addUrlPatterns("/*");
    return filterRegistrationBean;
}

修改后重新启动,异常即可解决。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 01:35:04