ugrade spring boot 2.0.0.RC2 exception No ServletContext set

时间:2018-02-25 09:07:35

标签: spring-boot

调试后,问题是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个常见帧

2 个答案:

答案 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需要。

我希望这个“视觉”示例有帮助。

欢呼