1、概览 {#1概览}
本文将会带你了解在 Spring Boot 启动时出现 ApplicationContextException
异常的原因,以及解决办法:
ApplicationContextException: Unable to start ServletWebServerApplicationContext due to missing ServletWebServerFactory bean
2、可能的原因 {#2可能的原因}
异常信息,"由于缺少 ServletWebServerFactory Bean,无法启动 ServletWebServerApplicationContext" 说明了一切。ApplicationContext
中没有配置 ServletWebServerFactory
Bean。
该异常主要出现在 Spring Boot 无法启动 ServletWebServerApplicationContext 时。为什么会这样?因为 ServletWebServerApplicationContext
使用包含的 ServletWebServerFactory
Bean 来启动自身。
一般来说,Spring Boot 通过 SpringApplication.run
方法来启动 Spring 应用。
SpringApplication
类会根据应用类型(如,Web 应用),尝试创建正确的 ApplicationContext
。
用于确定是否是 Web 应用的算法来自于一些依赖,如 spring-boot-starter-web
。缺少这些依赖,可能是导致异常的原因之一。
另一个原因是 Spring Boot 启动类中缺少 @SpringBootApplication
注解。
3、重现异常 {#3重现异常}
创建一个示例应用,故意在 main 类上不添加 @SpringBootApplication
注解。
public class MainEntryPoint {
public static void main(String[] args) {
SpringApplication.run(MainEntryPoint.class, args);
}
}
启动应用,会抛出异常。如下:
22:20:39.134 [main] ERROR 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 com.baeldung.applicationcontextexception.MainEntryPoint.main(MainEntryPoint.java:10)
<strong>Caused by: org.springframework.context.ApplicationContextException: Unable to start ServletWebServerApplicationContext due to missing ServletWebServerFactory bean.</strong>
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.getWebServerFactory(ServletWebServerApplicationContext.java:209)
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.createWebServer(ServletWebServerApplicationContext.java:179)
...
如上,符合预期。启动时抛出了 "ApplicationContextException: Unable to start ServletWebServerApplicationContext due to missing ServletWebServerFactory bean" 异常。
4、修复异常 {#4修复异常}
修复异常的简单方法是在 MainEntryPoint
启动类上添加 @SpringBootApplication
注解。
通过此注解,告诉 Spring Boot 自动配置必要的 Bean 并将其注册到上下文中。
也可以通过禁用 Web 环境来避免非 Web 应用出现异常。为此,可以使用 spring.main.web-application-type
属性。
在 application.properties
配置文件中进行配置:
spring.main.web-application-type=none
在 application.yml
中同理:
spring:
main:
web-application-type: none
none
表示应用不应作为 Web 应用运行,用于禁用 Web 服务器。
从 Spring Boot 2.0 开始,也可以使用 SpringApplicationBuilder
来明确定义特定类型的 Web 应用:
@SpringBootApplication
public class MainClass {
public static void main(String[] args) {
new SpringApplicationBuilder(MainClass.class)
.web(WebApplicationType.NONE)
.run(args);
}
}
对于 WebFlux 项目,可以使用 WebApplicationType.REACTIVE
。
另一种解决方案是排除 spring-webmvc
依赖。
由于 classpath 中存在该依赖,Spring Boot 会将该项目视为 Servlet 应用,而不是响应式 Web 应用。因此 Spring Boot 无法启动 ServletWebServerApplicationContext
。
5、总结 {#5总结}
本文介绍了 Spring Boot 启动时出现 "ApplicationContextException: Unable to start ServletWebServerApplicationContext due to missing ServletWebServerFactory bean" 异常的原因,以及解决办法。
Ref:https://www.baeldung.com/spring-boot-application-context-exception