调试后,问题是mvc配置类EnableWebMvcConfiguration加载太早,servlet尚未加载。
org.springframework.beans.factory.BeanCreationException:创建名称为' resourceHandlerMapping'的bean时出错在类路径资源中定义[org / springframework / boot / autoconfigure / web / servlet / WebMvcAutoConfiguration $ EnableWebMvcConfiguration.class]:通过工厂方法进行Bean实例化失败;嵌套异常是org.springframework.beans.BeanInstantiationException:无法实例化[org.springframework.web.servlet.HandlerMapping]:工厂方法' resourceHandlerMapping'抛出异常;嵌套异常是java.lang.IllegalStateException:没有设置ServletContext 在org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:587)〜[spring-beans-5.0.4.RELEASE.jar:5.0.4.RELEASE] 在org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1250)~ [spring-beans-5.0.4.RELEASE.jar:5.0.4.RELEASE] 在org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1099)〜[spring-beans-5.0.4.RELEASE.jar:5.0.4.RELEASE] 在org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:545)〜[spring-beans-5.0.4.RELEASE.jar:5.0.4.RELEASE] 在org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:502)〜[spring-beans-5.0.4.RELEASE.jar:5.0.4.RELEASE] 在org.springframework.beans.factory.support.AbstractBeanFactory.lambda $ doGetBean $ 0(AbstractBeanFactory.java:312)〜[spring-beans-5.0.4.RELEASE.jar:5.0.4.RELEASE] at org.springframework.beans.factory.support.AbstractBeanFactory $$ Lambda $ 125 / 98506158.getObject(Unknown Source)〜[na:na] 在org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)~ [spring-beans-5.0.4.RELEASE.jar:5.0.4.RELEASE] 在org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:310)〜[spring-beans-5.0.4.RELEASE.jar:5.0.4.RELEASE] 在org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200)〜[spring-beans-5.0.4.RELEASE.jar:5.0.4.RELEASE] 在org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:760)〜[spring-beans-5.0.4.RELEASE.jar:5.0.4.RELEASE] 在org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:868)〜[spring-context-5.0.4.RELEASE.jar:5.0.4.RELEASE] 在org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:549)〜[spring-context-5.0.4.RELEASE.jar:5.0.4.RELEASE] 在org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:140)〜[spring-boot-2.0.0.RC2.jar:2.0.0.RC2] 在org.springframework.boot.SpringApplication.refresh(SpringApplication.java:752)[spring-boot-2.0.0.RC2.jar:2.0.0.RC2] 在org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:388)[spring-boot-2.0.0.RC2.jar:2.0.0.RC2] 在org.springframework.boot.SpringApplication.run(SpringApplication.java:327)[spring-boot-2.0.0.RC2.jar:2.0.0.RC2] 在org.springframework.boot.SpringApplication.run(SpringApplication.java:1246)[spring-boot-2.0.0.RC2.jar:2.0.0.RC2] 在org.springframework.boot.SpringApplication.run(SpringApplication.java:1234)[spring-boot-2.0.0.RC2.jar:2.0.0.RC2] 在com.manway.BccApplication.main(BccApplication.java:16)[main /:na] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)〜[na:1.8.0_40] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)〜[na:1.8.0_40] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)〜[na:1.8.0_40] 在java.lang.reflect.Method.invoke(Method.java:497)〜[na:1.8.0_40] 在org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49)[spring-boot-devtools-2.0.0.RC2.jar:2.0.0.RC2] 引起:org.springframework.beans.BeanInstantiationException:无法实例化[org.springframework.web.servlet.HandlerMapping]:工厂方法' resourceHandlerMapping'抛出异常;嵌套异常是java.lang.IllegalStateException:没有设置ServletContext 在org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:185)〜[spring-beans-5.0.4.RELEASE.jar:5.0.4.RELEASE] 在org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:579)〜[spring-beans-5.0.4.RELEASE.jar:5.0.4.RELEASE] ...省略了24个常用帧 引起:java.lang.IllegalStateException:没有设置ServletContext 在org.springframework.util.Assert.state(Assert.java:73)〜[spring-core-5.0.4.RELEASE.jar:5.0.4.RELEASE] 在org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport.resourceHandlerMapping(WebMvcConfigurationSupport.java:485)〜[spring-webmvc-5.0.4.RELEASE.jar:5.0.4.RELEASE] at org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration $ EnableWebMvcConfiguration $$ EnhancerBySpringCGLIB $$ 5de64506.CGLIB $ resourceHandlerMapping $ 40()〜[spring-boot-autoconfigure-2.0.0.RC2.jar:2.0.0.RC2 ] at org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration $ EnableWebMvcConfiguration $$ EnhancerBySpringCGLIB $$ 5de64506 $$ FastClassBySpringCGLIB $$ edc706a5.invoke()〜[spring-boot-autoconfigure-2.0.0.RC2.jar:2.0。 0.RC2] 在org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228)〜[spring-core-5.0.4.RELEASE.jar:5.0.4.RELEASE] 在org.springframework.context.annotation.ConfigurationClassEnhancer $ BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:361)〜[spring-context-5.0.4.RELEASE.jar:5.0.4.RELEASE] at org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration $ EnableWebMvcConfiguration $$ EnhancerBySpringCGLIB $$ 5de64506.resourceHandlerMapping()〜[spring-boot-autoconfigure-2.0.0.RC2.jar:2.0.0.RC2] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)〜[na:1.8.0_40] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)〜[na:1.8.0_40] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)〜[na:1.8.0_40] 在java.lang.reflect.Method.invoke(Method.java:497)〜[na:1.8.0_40] 在org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:154)〜[spring-beans-5.0.4.RELEASE.jar:5.0.4.RELEASE] ...省略了25个常见帧
答案 0 :(得分:17)
“调试后,问题是mvc配置类EnableWebMvcConfiguration加载太早,servlet尚未加载。”
我花了几个小时的时间。 我设法找到了这种情况发生的原因。 我的配置被分成几个文件,我在Security Config(之前创建的)中创建了一个与MVC相关的bean,强制在它的时间之前使用MVC配置。
解决方案是将@Bean实例从安全配置移动到MVC配置。 我希望它能帮助其他人!
答案 1 :(得分:6)
我遇到了同样的“ No ServletContext set”问题,我想通过做一个简单的演示来理解,该演示对我有帮助。因此,我正在分享我的简单演示,希望它也对您有所帮助。
注意:
(1)我使用的示例与OP稍有不同,但概念和问题相同。
(2)我删除了一些与此演示无关的日志。
Spring Boot Application简单内容-仅3类:
(1)用@SpringBootApplication注释的主类BeanLoadingDemoApplication
,
(2)一个class WebSecurityConfiguration extends WebSecurityConfigurerAdapter
,它会覆盖一个configure
方法
(3)和几个测试Bean,一个在独立的@Configuration
类中,另一个在(2)的主@SpringBootApplication
类中,另一个
启动应用程序后的日志如下。只需关注该部分在日志中的位置:
INFO o.s.web.context.ContextLoader - Root WebApplicationContext: initialization completed in 700 ms INFO c.example.demo.WebSecurityConfiguration - WebSecurityConfiguration() - Constructor
INFO c.e.demo.BeanLoadingDemoApplication - Starting BeanLoadingDemoApplication
INFO o.s.b.w.embedded.tomcat.TomcatWebServer - Tomcat initialized with port(s): 8080 (http)
INFO o.a.c.c.C.[Tomcat].[localhost].[/] - Initializing Spring embedded WebApplicationContext
INFO o.s.web.context.ContextLoader - Root WebApplicationContext: initialization completed in 700 ms
INFO c.example.demo.WebSecurityConfiguration - WebSecurityConfiguration() - Constructor
INFO com.example.demo.TestBeanConfiguration - #############################
INFO com.example.demo.TestBeanConfiguration - @Configuration - @Bean - testBean()
INFO com.example.demo.TestBeanConfiguration - #############################
INFO c.e.demo.BeanLoadingDemoApplication - #############################
INFO c.e.demo.BeanLoadingDemoApplication - @SringBootApp - @Bean - testBean2
INFO c.e.demo.BeanLoadingDemoApplication - #############################
INFO c.example.demo.WebSecurityConfiguration - =======================================
INFO c.example.demo.WebSecurityConfiguration - @Configuration - WebSecurityConfiguration - @Override configure
INFO c.example.demo.WebSecurityConfiguration - =======================================
INFO c.e.demo.BeanLoadingDemoApplication - Started BeanLoadingDemoApplication in 1.371 seconds (JVM running for 2.326)
到目前为止好吗?简单吧?现在我添加一个
@Bean
public ServletWebServerFactory servletContainer() {
TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory();
...
}
类WebSecurityConfiguration
中的可以为Tomcat配置第二个连接器。只需将焦点放在该部分“移动”的位置:
WebSecurityConfiguration()-构造函数
您是否可以看到在启动应用程序后立即调用了构造函数,并且在初始化根WebApplicationContext
之前构造了该构造函数?到目前为止,问题很明显。
INFO c.e.demo.BeanLoadingDemoApplication - Starting BeanLoadingDemoApplication
INFO c.example.demo.WebSecurityConfiguration - WebSecurityConfiguration() - Constructor
INFO o.s.b.w.embedded.tomcat.TomcatWebServer - Tomcat initialized with port(s): 8080 (http) 8080 (http)
INFO o.a.c.c.C.[Tomcat].[localhost].[/] - Initializing Spring embedded WebApplicationContext
INFO o.s.web.context.ContextLoader - Root WebApplicationContext: initialization completed in 785 ms
INFO com.example.demo.TestBeanConfiguration - #############################
INFO com.example.demo.TestBeanConfiguration - @Configuration - @Bean - testBean()
INFO com.example.demo.TestBeanConfiguration - #############################
INFO c.e.demo.BeanLoadingDemoApplication - #############################
INFO c.e.demo.BeanLoadingDemoApplication - @SringBootApp - @Bean - testBean2
INFO c.e.demo.BeanLoadingDemoApplication - #############################
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'resourceHandlerMapping' defined in class path resource
Caused by: java.lang.IllegalStateException: No ServletContext set
原因是由于Spring Boot
在创建自己的Tomcat
之前正在初始化嵌入式WebApplicationContext
,因此需要配置我是的连接器在初始化Tomcat之前和初始化Root WebApplicationContext之前,通过Tomcat
向@Bean
添加!但是因为我的@Bean
在{{1}中},该类的构建早于应有的构建,因此将没有ServletContext!
解决方案是移动此
WebSecurityConfiguration class
在@Bean
public ServletWebServerFactory servletContainer() {
TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory();
...
}
独立类中,这样不会@Configuration
的构造函数早于应有的调用,这样,它将获得WebSecurityConfiguration
需要。
我希望这个“视觉”示例有帮助。
欢呼