Unable to start ServletWebServerApplicationContext due to missing ServletWebServerFactory bean异常解析
Spring Boot升级到2.0.0,Maven构建成功,但是使用tomcat或jetty容器启动应用总是报错如下:"C:\Program Files\Java\jdk1.8.0_161\bin\java" ......... com.fangxing.javalearning.annotationlearning.ComponentScanApphello world._...
Spring Boot升级到2.0.0,Maven构建成功,但是使用tomcat或jetty容器启动应用总是报错如下:
"C:\Program Files\Java\jdk1.8.0_161\bin\java" ......... com.fangxing.javalearning.annotationlearning.ComponentScanApp
hello world
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.0.0.RELEASE)
2018-04-03 22:25:07.232 INFO 4976 --- [ main] c.f.j.a.ComponentScanApp : Starting ComponentScanApp on DESKTOP-BHGM3HS with PID 4976 (started by hasee in D:\test\projects\java-learning)
2018-04-03 22:25:07.237 INFO 4976 --- [ main] c.f.j.a.ComponentScanApp : No active profile set, falling back to default profiles: default
2018-04-03 22:25:07.321 INFO 4976 --- [ main] ConfigServletWebServerApplicationContext : Refreshing org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@45f45fa1: startup date [Tue Apr 03 22:25:07 CST 2018]; root of context hierarchy
2018-04-03 22:25:07.664 WARN 4976 --- [ main] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.context.ApplicationContextException: Unable to start web server; nested exception is org.springframework.context.ApplicationContextException: Unable to start ServletWebServerApplicationContext due to missing ServletWebServerFactory bean.
2018-04-03 22:25:08.238 ERROR 4976 --- [ main] o.s.boot.SpringApplication : Application run failed
org.springframework.context.ApplicationContextException: Unable to start web server; nested exception is org.springframework.context.ApplicationContextException: Unable to start ServletWebServerApplicationContext due to missing ServletWebServerFactory bean.
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.onRefresh(ServletWebServerApplicationContext.java:155) ~[spring-boot-2.0.0.RELEASE.jar:2.0.0.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543) ~[spring-context-5.0.4.RELEASE.jar:5.0.4.RELEASE]
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:140) ~[spring-boot-2.0.0.RELEASE.jar:2.0.0.RELEASE]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:752) [spring-boot-2.0.0.RELEASE.jar:2.0.0.RELEASE]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:388) [spring-boot-2.0.0.RELEASE.jar:2.0.0.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:327) [spring-boot-2.0.0.RELEASE.jar:2.0.0.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1246) [spring-boot-2.0.0.RELEASE.jar:2.0.0.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1234) [spring-boot-2.0.0.RELEASE.jar:2.0.0.RELEASE]
at com.fangxing.javalearning.annotationlearning.ComponentScanApp.main(ComponentScanApp.java:15) [classes/:na]
Caused by: org.springframework.context.ApplicationContextException: Unable to start ServletWebServerApplicationContext due to missing ServletWebServerFactory bean.
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.getWebServerFactory(ServletWebServerApplicationContext.java:204) ~[spring-boot-2.0.0.RELEASE.jar:2.0.0.RELEASE]
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.createWebServer(ServletWebServerApplicationContext.java:178) ~[spring-boot-2.0.0.RELEASE.jar:2.0.0.RELEASE]
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.onRefresh(ServletWebServerApplicationContext.java:152) ~[spring-boot-2.0.0.RELEASE.jar:2.0.0.RELEASE]
... 8 common frames omitted
Process finished with exit code 1
分析如下:
一、SpringBoot默认的容器为Tomcat,依赖包在spring-boot-starter-web下
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
二、SpringBoot把容器修改为Jetty
在pom.xml文件中,在引用的spring-boot-starter-web排除Tomcat的依赖包,然后再引入Jetty容器的依赖包,如下:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- Jetty适合长连接应用,就是聊天类的长连接 -->
<!-- 使用Jetty,需要在spring-boot-starter-web排除spring-boot-starter-tomcat,因为SpringBoot默认使用tomcat -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jetty</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
三、为什么可以这样切换呢?
从SpringBoot源码中查看一下org.springframework.boot.autoconfigure.web.EmbeddedServletContainerAutoConfiguration类可知,使用哪个容器已经配置好,是根据依赖的Jar包自动切换,
加载Tomcat容器类代码和Jetty容器类代码如下:
/**
* Nested configuration if Tomcat is being used.
*/
@Configuration
@ConditionalOnClass({ Servlet.class, Tomcat.class })
@ConditionalOnMissingBean(value = EmbeddedServletContainerFactory.class, search = SearchStrategy.CURRENT)
public static class EmbeddedTomcat {
@Bean
public TomcatEmbeddedServletContainerFactory tomcatEmbeddedServletContainerFactory() {
return new TomcatEmbeddedServletContainerFactory();
}
}
/**
* Nested configuration if Jetty is being used.
*/
@Configuration
@ConditionalOnClass({ Servlet.class, Server.class, Loader.class,
WebAppContext.class })
@ConditionalOnMissingBean(value = EmbeddedServletContainerFactory.class, search = SearchStrategy.CURRENT)
public static class EmbeddedJetty {
@Bean
public JettyEmbeddedServletContainerFactory jettyEmbeddedServletContainerFactory() {
return new JettyEmbeddedServletContainerFactory();
}
}
类上@ConditionalOnClass注解,根据存在的依赖的容器Jar包判断使用哪个容器。
而Spring Boot启动出现错误,错误内容大概的意思是:未能加载嵌入的供web应用加载的空间,是因为缺少ServletWebServerFactory bean
在StackOverflow论坛中发现,这个问题与“Unable to start EmbeddedWebApplicationContext due to missing EmbeddedServletContainerFactory bean”如出一辙。
在stackflow上面看到了这个错误的解决办法,原文如下:
The scheduling guide isn't a web app so you probably have some mouldy stuff in your pom.xml from the REST guide? If you follow the instructions closely it should work. Another potential issue with the code you posted above is that your @EnableAutoConfigurationclass is not used in the context, only as a main method (which may not be a problem for the scheduling guide but it probably is for a bunch of others).
这里意思是添加一个@EnableAutoConfiguration注解来解决问题。
其实不是技术论坛中大家常说的应用入口类缺少@SpringBootApplication标注,或者是Spring bean缺少@EnableAutoConfiguration标注等问题。
Spring Boot应用起不来,是因为默认使用的嵌入式Tomcat容器无法启动,即是容器依赖jar出问题了,最有可能原因是网上不好导致下载依赖包的过程中出现卡死或中断。
最直接的解决办法是删除Maven本地库中与容器包相关的依赖jar,再次构建下载新的jar。
启动Spring Boot应用,就可问题解决。
更多推荐
所有评论(0)