Caused by: org.springframework.context.ApplicationContextException: Unable to start ServletWebServer

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:156)
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:544)
	at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:141)
	at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:747)
	at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:315)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1226)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1215)
	at com.xx.XXApplication.main(XXApplication.java:11)
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:203)
	at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.createWebServer(ServletWebServerApplicationContext.java:179)
	at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.onRefresh(ServletWebServerApplicationContext.java:153)
	... 8 common frames omitted

新加了个包,编译正常,启动出现错误,所以问题一定在我新加的包里(此处的包省略,假设为jj-xx),这个包里的jj-xx依赖有

[INFO]       +- javax.servlet:javax.servlet-api:jar:4.0.1:compile
[INFO]       +- javax.servlet.jsp:jsp-api:jar:2.2:compile
[INFO]       +- org.eclipse.jetty:jetty-server:jar:9.4.20.v20190813:compile
[INFO]       |  +- org.eclipse.jetty:jetty-http:jar:9.4.20.v20190813:compile
[INFO]       |  |  \- org.eclipse.jetty:jetty-util:jar:9.4.20.v20190813:compile
[INFO]       |  \- org.eclipse.jetty:jetty-io:jar:9.4.20.v20190813:compile
[INFO]       +- org.codehaus.groovy:groovy-all:jar:2.4.13:compile
[INFO]       +- org.apache.commons:commons-exec:jar:1.3:compile
[INFO]       \- cglib:cglib:jar:2.1:compile
[INFO]          +- asm:asm:jar:1.5.3:compile
[INFO]          +- asm:asm-util:jar:1.3.4:compile
[INFO]          \- aspectwerkz:aspectwerkz-core:jar:0.8.1:compile

另外因为一些上下文需要,之前还引入了spring-web相关的依赖(这里猜想可能是因为一些包的必要条件满足才导致程序启动为web程序

	<dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>xxx</version>
        </dependency>

如下是解决方式

根据报错提示,application启动的时候,根据webApplicationType判断的运行环境

 protected ConfigurableApplicationContext createApplicationContext() {
       Class<?> contextClass = this.applicationContextClass;
       if (contextClass == null) {
           try {
               switch(this.webApplicationType) {
               case SERVLET:
                   contextClass = Class.forName("org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext");

继续往下看,webApplicationType是deduceFromClasspath生成的

        this.webApplicationType = WebApplicationType.deduceFromClasspath();

最后是deduceFromClasspath方法里,返回servlet方法的逻辑,大概有三种情况

  • 存在org.springframework.web.reactive.DispatcherHandler && 不存在org.springframework.web.servlet.DispatcherServlet && 不存在org.glassfish.jersey.servlet.ServletContainer,为REACTIVE程序
  • SERVLET_INDICATOR_CLASSES字符串数组里有一个不存在时,为非web程序
  • SERVLET_INDICATOR_CLASSES都存在时,为SERVLET环境
    注: String[] SERVLET_INDICATOR_CLASSES = new String[]{"javax.servlet.Servlet", "org.springframework.web.context.ConfigurableWebApplicationContext"};
static WebApplicationType deduceFromClasspath() {
        if (ClassUtils.isPresent("org.springframework.web.reactive.DispatcherHandler", (ClassLoader)null) && !ClassUtils.isPresent("org.springframework.web.servlet.DispatcherServlet", (ClassLoader)null) && !ClassUtils.isPresent("org.glassfish.jersey.servlet.ServletContainer", (ClassLoader)null)) {
            return REACTIVE;
        } else {
            String[] var0 = SERVLET_INDICATOR_CLASSES;
            int var1 = var0.length;

            for(int var2 = 0; var2 < var1; ++var2) {
                String className = var0[var2];
                if (!ClassUtils.isPresent(className, (ClassLoader)null)) {
                    return NONE;
                }
            }

            return SERVLET;
        }
    }

综上所述,只存在spring-web时还是非web程序,当我引入依赖并引入其他有关javax.servlet.Servlet 时,就导致我的运行程序为SERVLET。

另外还提供另一种解决方式
外层配置里加上,这是创建 Environment
根据准备阶段的推断 Web 应用类型创建对应的 ConfigurableEnvironment 实例:

spring.main.web-application-type=none
#spring.main.web-application-type=servlet

private ConfigurableEnvironment getOrCreateEnvironment() {
        if (this.environment != null) {
            return this.environment;//这里就是根据外层配置去获取的none类型
        } else {
            switch(this.webApplicationType) {
            case SERVLET:
                return new StandardServletEnvironment();
            case REACTIVE:
                return new StandardReactiveWebEnvironment();
            default:
                return new StandardEnvironment();
            }
        }
    }
    ```
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值