【问题标题】:How to prevent spring-boot autoconfiguration for spring-web?如何防止spring-web的spring-boot自动配置?
【发布时间】:2015-06-30 06:56:26
【问题描述】:

我正在使用 spring-boot 并在 maven pom 中添加了 spring-web 依赖项,以使用 RestTemplate

现在 spring 尝试初始化一个EmbeddedServletContext。如何预防?

Exception in thread "main" org.springframework.context.ApplicationContextException: Unable to start embedded container; nested exception is org.springframework.context.ApplicationContextException: Unable to start EmbeddedWebApplicationContext due to missing EmbeddedServletContainerFactory bean.
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.onRefresh(EmbeddedWebApplicationContext.java:133)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:474)
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:118)
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:686)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:320)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:957)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:946)
Caused by: org.springframework.context.ApplicationContextException: Unable to start EmbeddedWebApplicationContext due to missing EmbeddedServletContainerFactory bean.
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.getEmbeddedServletContainerFactory(EmbeddedWebApplicationContext.java:183)
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.createEmbeddedServletContainer(EmbeddedWebApplicationContext.java:156)
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.onRefresh(EmbeddedWebApplicationContext.java:130)
    ... 8 more

【问题讨论】:

    标签: java spring spring-boot spring-web


    【解决方案1】:

    我尝试使用 Spring Boot 2.06 构建响应式 Web 应用程序并收到此错误:

    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.6.RELEASE.jar:2.0.6.RELEASE]
        at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:542) ~[spring-context-5.0.10.RELEASE.jar:5.0.10.RELEASE]
        at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:140) ~[spring-boot-2.0.6.RELEASE.jar:2.0.6.RELEASE]
        at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:754) [spring-boot-2.0.6.RELEASE.jar:2.0.6.RELEASE]
        at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:386) [spring-boot-2.0.6.RELEASE.jar:2.0.6.RELEASE]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:307) [spring-boot-2.0.6.RELEASE.jar:2.0.6.RELEASE]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1242) [spring-boot-2.0.6.RELEASE.jar:2.0.6.RELEASE]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1230) [spring-boot-2.0.6.RELEASE.jar:2.0.6.RELEASE]
        at com.vogella.springboot2.Test3Application.main(Test3Application.java:10) [main/: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.6.RELEASE.jar:2.0.6.RELEASE]
        at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.createWebServer(ServletWebServerApplicationContext.java:178) ~[spring-boot-2.0.6.RELEASE.jar:2.0.6.RELEASE]
        at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.onRefresh(ServletWebServerApplicationContext.java:152) ~[spring-boot-2.0.6.RELEASE.jar:2.0.6.RELEASE]
        ... 8 common frames omitted
    

    此链接解释了问题,并提供了两个建议:

    https://vividcode.io/Fixing-Spring-Boot-error-Unable-to-start-ServletWebServerApplicationContext-due-to-missing-ServletWebServerFactory-bean/

    我正在使用 Spring Boot 构建一个新的 Spring WebFlux 应用程序。 从 start.spring.io 下载项目模板后,我添加了 一些第三方依赖项并尝试启动应用程序。然后 我遇到了错误 org.springframework.context.ApplicationContextException:无法 由于缺少启动 ServletWebServerApplicationContext ServletWebServerFactory bean....

    错误信息是解决问题的线索。它说无法启动 ServletWebServerApplicationContext,但我的项目使用的是 WebFlux 它是一个响应式 Web 项目,而不是基于 servlet 的 Spring Web MVC 项目。

    调试 Spring 源代码帮助我找到了原因。在里面 方法 deuceWebApplicationType 的 org.springframework.boot.SpringApplication,web应用类型 仅当 Spring Web 的类时才设置为 WebApplicationType.REACTIVE CLASSPATH 中不存在 MVC。

    一旦确定了根本原因,解决方案就很容易了。我们可以:

    更新Maven依赖排除spring-webmvc,或者设置web 将应用程序类型显式设置为 WebApplicationType.REACTIVE,如图所示 下面。

    @SpringBootApplication class MyApplication
    fun main(args: Array<String>) {
        val app = SpringApplication(MyApplication::class.java)
        app.webApplicationType = WebApplicationType.REACTIVE
        app.run(*args)
    }
    

    不幸的是,这些解决方案都不适合我。相反,我调整了 geoand 的回复,并将其添加到我的application.properties

    spring.main.web-application-type=reactive
    

    瞧!问题已解决!

    【讨论】:

      【解决方案2】:

      这适用于 Spring Boot 2.x

      public static void main(String[] args) {
         new SpringApplicationBuilder(MyApplication.class)
                  .web(WebApplicationType.NONE)
                  .build()
                  .run(args);
      }
      

      【讨论】:

        【解决方案3】:

        虽然禁用 Web 环境的旧方法(如 @Tim 的回答中所述)在 Spring Boot 2.x 中仍然有效,但新的首选方法是设置以下属性

        spring.main.web-application-type=none

        Here 是定义允许值的枚举

        【讨论】:

        • 链接页面没有提供有关 spring.main.web-application-type 属性的任何信息(当我写这篇文章时),甚至没有提供有效值是什么。谷歌搜索Spring WebApplicationType API 将显示有效值为servletreactivenone(我猜是小写的)。
        • @ddekany 他们一定更改了文档。感谢您指出这一点!
        【解决方案4】:

        供参考:此用例记录在Spring Boot Reference Guide

        并非所有 Spring 应用程序都必须是 Web 应用程序(或 Web 服务)。如果您想在 main 方法中执行一些代码,同时还要引导一个 Spring 应用程序来设置要使用的基础设施,那么使用 Spring Boot 的 SpringApplication 功能很容易。 SpringApplication 更改其 ApplicationContext 类取决于它是否认为需要 Web 应用程序。您可以做的第一件事就是将 servlet API 依赖项从类路径中移除。如果您不能这样做(例如,您从同一代码库运行 2 个应用程序),那么您可以显式调用 SpringApplication.setWebEnvironment(false),或设置 applicationContextClass 属性(通过 Java API 或使用外部属性)。您希望作为业务逻辑运行的应用程序代码可以实现为 CommandLineRunner,并作为 @Bean 定义放入上下文中。

        application.properties:

        spring.main.web-environment=false   #webEnvironment property
        

        【讨论】:

        • 非弃用版本现在是 spring.main.web-environment-type=none
        • 也许他们又改了,但现在是spring.main.web-application-type
        【解决方案5】:

        第一招:

        public static void main(String[] args) throws Exception {
            ConfigurableApplicationContext ctx = new SpringApplicationBuilder(Application.class)
                        .web(false)
                        .run(args);
        }
        

        第二:

        @Configuration
        @EnableAutoConfiguration(exclude = WebMvcAutoConfiguration.class)
        public class Application {
        

        【讨论】:

        • 我尝试了@EnableAutoConfiguration(exclude = WebMvcAutoConfiguration.class, EmbeddedServletContainerAutoConfiguration.class}),但仍然出现同样的错误...如果spring-web 的自动配置可以通过注释禁用,而无需修改我的主要启动方法,那就太好了...跨度>
        • 虽然您的建议有效,但谢谢!但无论如何,只禁用基于自动配置注释会很好。
        • spring.main.web_environment=false 更好不过...无需编写任何 Java 代码 :-)
        • @membersound 我今天遇到了同样的问题。我最终放弃了 RestTemplate 进行改造:square.github.io/retrofit ... 一方面,它摆脱了我的类路径中的 spring-web 依赖。对于两个人来说,推理和阅读要容易得多。
        猜你喜欢
        • 2016-11-21
        • 2020-06-14
        • 1970-01-01
        • 1970-01-01
        • 2018-05-14
        • 2019-10-21
        • 2017-01-19
        • 2018-09-09
        • 2018-09-06
        相关资源
        最近更新 更多