如何防止spring-web的spring-boot自动配置?
Posted
技术标签:
【中文标题】如何防止spring-web的spring-boot自动配置?【英文标题】:How to prevent spring-boot autoconfiguration for spring-web? 【发布时间】: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
【问题讨论】:
【参考方案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
将显示有效值为servlet
、reactive
和none
(我猜是小写的)。
@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 依赖。对于两个人来说,推理和阅读要容易得多。以上是关于如何防止spring-web的spring-boot自动配置?的主要内容,如果未能解决你的问题,请参考以下文章
Spring-web源码解析之ContentNegotiationStrategy