Spring Boot 启动异常:ApplicationContextException

1、概览

本文将会带你了解在 Spring Boot 启动时出现 ApplicationContextException 异常的原因,以及解决办法:

ApplicationContextException: Unable to start ServletWebServerApplicationContext due to missing ServletWebServerFactory bean

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、重现异常

创建一个示例应用,故意在 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、修复异常

修复异常的简单方法是在 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、总结

本文介绍了 Spring Boot 启动时出现 “ApplicationContextException: Unable to start ServletWebServerApplicationContext due to missing ServletWebServerFactory bean” 异常的原因,以及解决办法。


Ref:https://www.baeldung.com/spring-boot-application-context-exception