ugrade spring boot 2.0.0.RC2 exception无ServletContext设置

Ric*_*ard 6 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:没有在org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:587)设置的ServletContext~ [spring-beans-5.0.4.RELEASE.jar:5.0.4 .RELEASE] org.springframework.beans上的org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1250)~ [spring-beans-5.0.4.RELEASE.jar:5.0.4.RELEASE] .factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1099)〜[spring-beans-5.0.4.RELEASE.jar:5.0.4.RELEASE] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(在Org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:502)〜[spring]的AbstractAutowireCapableBeanFactory.java:545)~ [spring-beans-5.0.4.RELEASE.jar:5.0.4.RELEASE] -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] at 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.context上的org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:760)~ [spring-beans-5.0.4.RELEASE.jar:5.0.4.RELEASE] .support.Abs org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:549)中的tractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:868)〜[spring-context-5.0.4.RELEASE.jar:5.0.4.RELEASE]〜 [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] at 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.SpringApplica 在com.manway.BccApplication.main(BccApplication.java:16)[main /:na]的.prun(SpringApplication.java:1234)[spring-boot-2.0.0.RC2.jar:2.0.0.RC2]在sun.reflect.DelegatingMethodAccessorImpl的sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)〜[na:1.8.0_40] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)〜[na:1.8.0_40].在org.springframework.boot.devtools的java.lang.reflect.Method.invoke(Method.java:497)〜[na:1.8.0_40]中调用(DelegatingMethodAccessorImpl.java:43)〜[na:1.8.0_40]. 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:没有在org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:185)〜[spring-beans-5.0.4.RELEASE.jar:5.0.4中设置的ServletContext .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:在org.springframework.util.Assert.state(Assert.java:73)中没有设置ServletContext~ [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] org.springframework.boot. autoconfigure.web.servlet.WebMvcAutoConfiguration $ EnableWebMvcConfiguration $$ EnhancerBySpringCGLIB $$ 5de64506.CGLIB $ resourceHandlerMapping $ 40()〜[spring-boot-autoconf 在org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration $ EnableNetMvcConfiguration $$ EnhancerBySpringCGLIB $$ 5de64506 $$ FastClassBySpringCGLIB $$ edc706a5.invoke()〜[ spring-boot-autoconfigure-2.0.0.RC2.jar:2.0.0.RC2] at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228)~ [spring-core-5.0.4.RELEASE .jar:5.0.4.RELEASE] at 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(原生方法)〜[na:1.8.0_40] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)〜[na:1.8.0_40] at sun.reflect.DelegatingMethod 在org.springframework.beans的java.lang.reflect.Method.invoke(Method.java:497)〜[na:1.8.0_40]中的AccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)〜[na:1.8.0_40]. factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:154)〜[spring-beans-5.0.4.RELEASE.jar:5.0.4.RELEASE] ...省略了25个常用帧

Est*_*ban 28

"经过调试,问题是mvc配置类EnableWebMvcConfiguration加载太早,servlet尚未加载."

我在这上花了几个小时.我设法找到了这种情况发生的原因.我的配置被分成几个文件,我在Security Config(之前创建的)中创建了一个与MVC相关的bean,强制在它的时间之前使用MVC配置.

解决方案是将@Bean实例从安全配置移动到MVC配置.我希望它能帮助其他人!


jum*_*key 8

我有同样的“No ServletContext set”问题,我想通过做一个简单的演示来理解,演示对我有帮助。所以我分享我的简单演示,希望它也能帮助你。

注意:
(1)我使用的示例与 OP略有不同,但概念和问题是相同的
(2) 我删除了一些与本演示无关的日志。

Spring Boot Application 简单内容 - 只有 3 个类:
(1) 一个BeanLoadingDemoApplication用 @SpringBootApplication 注释的主类,
(2) a class WebSecurityConfiguration extends WebSecurityConfigurerAdapter,它覆盖了一个configure方法
(3) 和几个测试 bean,1 个在独立@Configuration类中,以及@SpringBootApplication(2)中主类中的另一个

启动应用程序后的日志如下。只专注于其中,这部分是在日志中:

INFO  o.s.web.context.ContextLoader - Root WebApplicationContext: initialization completed in 700 ms
INFO  c.example.demo.WebSecurityConfiguration - WebSecurityConfiguration() - Constructor
Run Code Online (Sandbox Code Playgroud)
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)
Run Code Online (Sandbox Code Playgroud)



到此为止好吗?很简单吧?现在我添加一个

@Bean
public ServletWebServerFactory servletContainer() { 
    TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory();
...
}
Run Code Online (Sandbox Code Playgroud)

在课堂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
Run Code Online (Sandbox Code Playgroud)

原因是因为在创建自己Spring Boot的嵌入Tomcat之前初始化嵌入WebApplicationContext,因此它需要通过在初始化 Tomcat 之前和在 Root WebApplicationContext 初始化之前配置添加到的连接器!!但是因为 my in ,该类的构造比应有的要早得多,因此它不会有 ServletContext !Tomcat@Bean @BeanWebSecurityConfiguration class

解决方案是移动这个

@Bean
public ServletWebServerFactory servletContainer() {
    TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory();
    ...
}
Run Code Online (Sandbox Code Playgroud)

在一个@Configuration独立的类中,这样 的构造函数WebSecurityConfiguration不会比它应该被调用的更早,并且通过这样做,它将获得ServletContext它需要的。

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

干杯