Java 如何防止spring-web的spring-boot自动配置?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/29800584/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 08:37:56  来源:igfitidea点击:

How to prevent spring-boot autoconfiguration for spring-web?

javaspringspring-bootspring-web

提问by membersound

I'm using spring-bootand added spring-webdependency in maven pom, to make use of RestTemplate.

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

Now spring tries to initialize an EmbeddedServletContext. How can I prevent it?

现在 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

采纳答案by Tim

For reference: This use case is documented in the Spring Boot Reference Guide:

供参考:此用例记录在Spring Boot 参考指南中

Not all Spring applications have to be web applications (or web services). If you want to execute some code in a mainmethod, but also bootstrap a Spring application to set up the infrastructure to use, then it's easy with the SpringApplicationfeatures of Spring Boot. A SpringApplicationchanges its ApplicationContextclass depending on whether it thinks it needs a web application or not. The first thing you can do to help it is to just leave the servlet API dependencies off the classpath. If you can't do that (e.g. you are running 2 applications from the same code base) then you can explicitly call SpringApplication.setWebEnvironment(false), or set the applicationContextClassproperty (through the Java API or with external properties). Application code that you want to run as your business logic can be implemented as a CommandLineRunnerand dropped into the context as a @Beandefinition.

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

application.properties:

应用程序属性:

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

回答by Artem Bilan

First trick:

第一个技巧:

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

Second:

第二:

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

回答by geoand

Although the legacy way of disabling the web environment (as mentioned in @Tim's answer) still works in Spring Boot 2.x, however the new preferred way is by setting the following property

尽管禁用 Web 环境的传统方式(如@Tim 的回答中所述)在 Spring Boot 2.x 中仍然有效,但是新的首选方式是通过设置以下属性

spring.main.web-application-type=none

spring.main.web-application-type=none

Hereis the enum that defines the allowed values

是定义允许值的枚举

回答by Andy

This works in Spring Boot 2.x

这适用于 Spring Boot 2.x

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

回答by FoggyDay

I was trying to build a Reactive Web App with Spring Boot 2.06 and got this error:

我试图用 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

This link explained the problem, and offered two suggestions:

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

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

I was building a new Spring WebFlux application with Spring Boot. After downloading the project template from start.spring.io, I added some third-party dependencies and tried to start the application. Then I met the error org.springframework.context.ApplicationContextException: Unable to start ServletWebServerApplicationContext due to missing ServletWebServerFactory bean....

The error message is the clue to the solution. It says Unable to start ServletWebServerApplicationContext, but my project is using WebFlux and it's a reactive web project, not a servlet-based Spring Web MVC project.

Debugging into the Spring source code helped me find the cause. In the method deduceWebApplicationType of org.springframework.boot.SpringApplication, the web application type is set to WebApplicationType.REACTIVE only when classes of Spring Web MVC is not present in the CLASSPATH.

The solution is easy once the root cause is identified. We can either:

Update Maven dependencies to exclude spring-webmvc, or Set the web application type to WebApplicationType.REACTIVE explicitly, as shown below.

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

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: Unable to start ServletWebServerApplicationContext 由于缺少 ServletWebServerFactory bean....

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

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

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

更新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)
}

Unfortunately, neither of these solutions worked for me. Instead, I adapted geoand's response, and added this to my application.properties:

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

spring.main.web-application-type=reactive

Voila! Problem resolved!

瞧!问题解决!