用 undertow 服务器替换 spring-boot-keycloak 项目的 tomcat 会导致 IllegalStateException: No ServletContext set

Posted

技术标签:

【中文标题】用 undertow 服务器替换 spring-boot-keycloak 项目的 tomcat 会导致 IllegalStateException: No ServletContext set【英文标题】:Replacing tomcat with undertow server for spring-boot-keycloak project results in IllegalStateException: No ServletContext set 【发布时间】:2021-02-26 05:09:51 【问题描述】:

我正在尝试设置simple spring-boot example project(keycloak 教程),但我遇到了启动错误。唯一与原始配置不同的是,我想使用 undertow 服务器而不是 tomcat。

在没有任何更改的情况下运行主类是成功的(使用@SpringBootApplication 注释的主类)(mvn spring-boot:run after clean & install)(标准 tomcat 设置)。

在 pom 中进行以下更改后,出现错误:

java.lang.IllegalStateException: 没有设置 ServletContext

详情见下文:

POM 变化:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <exclusions>
        <exclusion>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-undertow</artifactId>
</dependency>

而不是

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

使用undertow时Spring boot启动出错:

12:48:55.077 [main] 错误 o.s.boot.SpringApplication - 应用程序运行 org.springframework.beans.factory.BeanCreationException 失败:错误 创建在类路径中定义的名称为“resourceHandlerMapping”的bean 资源 [org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration$EnableWebMvcConfiguration.class]: 通过工厂方法实例化 Bean 失败;嵌套异常是 org.springframework.beans.BeanInstantiationException:失败 实例化 [org.springframework.web.servlet.HandlerMapping]:工厂 方法“resourceHandlerMapping”抛出异常;嵌套异常是 java.lang.IllegalStateException:没有设置 ServletContext org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:655) 在 org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:635) 在 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1336) 在 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1176) 在 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:556) 在 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:516) 在 org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:324) 在 org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:226) 在 org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:322) 在 org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) 在 org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:897) 在 org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:879) 在 org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:551) 在 org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:143) 在 org.springframework.boot.SpringApplication.refresh(SpringApplication.java:758) 在 org.springframework.boot.SpringApplication.refresh(SpringApplication.java:750) 在 org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397) 在 org.springframework.boot.SpringApplication.run(SpringApplication.java:315) 在 org.springframework.boot.SpringApplication.run(SpringApplication.java:1237) 在 org.springframework.boot.SpringApplication.run(SpringApplication.java:1226) 在 com.baeldung.keycloak.SpringBoot.main(SpringBoot.java:11) 引起 作者:org.springframework.beans.BeanInstantiationException:失败 实例化 [org.springframework.web.servlet.HandlerMapping]:工厂 方法“resourceHandlerMapping”抛出异常;嵌套异常是 java.lang.IllegalStateException:没有设置 ServletContext org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:185) 在 org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:650) ...省略了20个常见的框架原因: java.lang.IllegalStateException:没有设置 ServletContext org.springframework.util.Assert.state(Assert.java:76) 在 org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport.resourceHandlerMapping(WebMvcConfigurationSupport.java:534) 在 java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native 方法)在 java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 在 java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 在 java.base/java.lang.reflect.Method.invoke(Method.java:566) 在 org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:154) ...省略了21个常用框架

使用的 Spring-boot.version 是 2.3.3.RELEASE(如父 pom 中所述)。

我怎样才能让它与 undertow 服务器一起工作?

【问题讨论】:

您是否能够在您的 java 配置中实例化 UndertowEmbeddedServletContainerFactory。参考baeldung.com/spring-boot-application-configuration 这不起作用(添加 bean)。它看起来也像过时的语法,我尝试使用 UndertowServletWebServerFactory 而不是 UndertowEmbeddedServletContainerFactory (不编译)。不幸的是,出现了同样的错误。 【参考方案1】:

固定

当如下所示的部分从原始的SecurityConfig类中分离出来时,它与undertow一起工作:

(新课程)

@Configuration
public class KeycloakConfig 
  @Bean
  public KeycloakSpringBootConfigResolver KeycloakConfigResolver() 
    return new KeycloakSpringBootConfigResolver();
  

【讨论】:

以上是关于用 undertow 服务器替换 spring-boot-keycloak 项目的 tomcat 会导致 IllegalStateException: No ServletContext set的主要内容,如果未能解决你的问题,请参考以下文章

SpringBoot 改用undertow 替换自带tomcat

springboot应用如何提高服务吞吐量

为什么建议你替换掉 SpringBoot 框架中的 Tomcat ?

为什么建议你替换掉 SpringBoot 框架中的 Tomcat ?

Spring Boot 内嵌容器Undertow取代tomcat

Undertow技术:为啥很多Spring Boot开发者放弃了Tomcat