Spring Boot 3.0调用ServerHttpResponse.setStatusCode引发ClassLoader问题
Spring Boot 2.7.X 迁移至3.0.X后ServerHttpResponse方法调用导致启动失败的解决方法
我在将Spring Boot从2.7.X版本迁移至3.0.X版本时,遇到应用无法正常启动的异常。示例代码如下:
public class ExampleFilter implements WebFilter { @Override @NonNull public Mono<Void> filter(ServerWebExchange exchange, @NonNull WebFilterChain chain) { var response = exchange.getResponse(); response.setStatusCode(HttpStatus.METHOD_NOT_ALLOWED); return chain.filter(exchange); } }
抛出的异常栈信息:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'allowedMethodsFilter': Lookup method resolution failed; nested exception is java.lang.IllegalStateException: Failed to introspect Class [tmp.AllowedMethodsFilter] from ClassLoader [org.springframework.boot.loader.LaunchedURLClassLoader@7eda2dbb] at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.determineCandidateConstructors(AutowiredAnnotationBeanPostProcessor.java:289) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.determineConstructorsFromBeanPostProcessors(AbstractAutowireCapableBeanFactory.java:1302) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1219) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:582) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542) at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:955) at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:918) at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:583) at org.springframework.boot.web.reactive.context.ReactiveWebServerApplicationContext.refresh(ReactiveWebServerApplicationContext.java:64) at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:745) at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:420) at org.springframework.boot.SpringApplication.run(SpringApplication.java:307) at org.springframework.boot.builder.SpringApplicationBuilder.run(SpringApplicationBuilder.java:164) at tmp.ExampleApp.main(ExampleApp.java:21) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:568) at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:49) at org.springframework.boot.loader.Launcher.launch(Launcher.java:108) at org.springframework.boot.loader.Launcher.launch(Launcher.java:58) at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:88) Caused by: java.lang.IllegalStateException: Failed to introspect Class [tmp.AllowedMethodsFilter] from ClassLoader [org.springframework.boot.loader.LaunchedURLClassLoader@7eda2dbb] at org.springframework.util.ReflectionUtils.getDeclaredMethods(ReflectionUtils.java:485) at org.springframework.util.ReflectionUtils.doWithLocalMethods(ReflectionUtils.java:321) at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.determineCandidateConstructors(AutowiredAnnotationBeanPostProcessor.java:267) ... 25 common frames omitted Caused by: java.lang.NoClassDefFoundError: org/springframework/http/HttpStatusCode at java.base/java.lang.Class.getDeclaredMethods0(Native Method) at java.base/java.lang.Class.privateGetDeclaredMethods(Class.java:3402) at java.base/java.lang.Class.getDeclaredMethods(Class.java:2504) at org.springframework.util.ReflectionUtils.getDeclaredMethods(ReflectionUtils.java:467) ... 27 common frames omitted Caused by: java.lang.ClassNotFoundException: org.springframework.http.HttpStatusCode at java.base/java.net.URLClassLoader.findClass(URLClassLoader.java:445) at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:587) at org.springframework.boot.loader.LaunchedURLClassLoader.loadClass(LaunchedURLClassLoader.java:151) at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:520) ... 31 common frames omitted
所有使用ServerHttpResponse的setStatusCode/getStatusCode方法的地方都会引发类似问题。
问题原因
- API重构与依赖版本不一致:Spring Framework 6.0(对应Spring Boot 3.0)引入了
HttpStatusCode接口作为状态码的统一抽象,ServerHttpResponse的setStatusCode方法参数类型从HttpStatus改为HttpStatusCode。如果项目中存在混合Spring 5.x和6.x版本的依赖,会导致HttpStatusCode类找不到的异常。 - Reactive逻辑不规范:设置响应状态码后继续调用
chain.filter(exchange)会导致响应生命周期冲突,不符合Reactive Web的处理规范。 - 过滤器命名冲突:自定义过滤器名称
allowedMethodsFilter可能与Spring Boot自动配置的过滤器重名,引发Bean初始化异常。
解决方案
1. 统一升级所有Spring相关依赖版本
检查项目依赖配置(Maven pom.xml/Gradle build.gradle),确保所有Spring Framework、Spring WebFlux等依赖的版本与Spring Boot 3.0完全对齐,避免混合不同版本的依赖。
2. 调整API调用方式(兼容新规范)
虽然HttpStatus实现了HttpStatusCode接口,直接传入HttpStatus.METHOD_NOT_ALLOWED语法上可行,但如果仍有问题,可显式转换:
response.setStatusCode(HttpStatusCode.valueOf(HttpStatus.METHOD_NOT_ALLOWED.value()));
3. 修正过滤器逻辑(符合Reactive规范)
设置响应状态码后,应直接返回完成信号终止请求处理,不再执行后续过滤器链:
public class ExampleFilter implements WebFilter { @Override @NonNull public Mono<Void> filter(ServerWebExchange exchange, @NonNull WebFilterChain chain) { ServerHttpResponse response = exchange.getResponse(); response.setStatusCode(HttpStatus.METHOD_NOT_ALLOWED); // 直接结束请求处理 return response.setComplete(); } }
4. 避免过滤器命名冲突
修改自定义过滤器的Bean名称,避免与Spring自动配置的过滤器重名:
@Bean public WebFilter exampleFilter() { return new ExampleFilter(); }
内容的提问来源于stack exchange,提问作者huhala
相关产品推荐
相关产品推荐

