【问题标题】:WebsocketServerContainer not in ServletContext after Tomcat-UpdateTomcat更新后WebsocketServerContainer不在ServletContext中
【发布时间】:2024-01-21 01:25:01
【问题描述】:

我刚刚将本地 tomcat(Windows 机器)从 9.0.10 升级到 9.0.14。 现在我在启动我的 Spring 应用程序(Spring Boot 2.1.1:MVC、Security、Websocket、Session)时得到以下 Stacktrace。

任何想法为什么会发生这种情况,tomcat 是否有任何已知的变化?我查找了更改日志,但那里什么也没有。

感谢任何建议或帮助!

 Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'createWebSocketContainer' defined in class path resource [com/my/spring/ws/MyWebsocketConfig.class]: Invocation of init method failed; nested exception is java.lang.IllegalStateException: Attribute 'javax.websocket.server.ServerContainer' not found in ServletContext
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1745)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:576)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:498)
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:320)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:318)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:827)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:863)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:546)
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:142)
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:775)
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:316)
    at org.springframework.boot.web.servlet.support.SpringBootServletInitializer.run(SpringBootServletInitializer.java:157)
    at com.my.spring.MyApplication.run(MyApplication.java:47)
    at org.springframework.boot.web.servlet.support.SpringBootServletInitializer.createRootApplicationContext(SpringBootServletInitializer.java:137)
    at org.springframework.boot.web.servlet.support.SpringBootServletInitializer.onStartup(SpringBootServletInitializer.java:91)
    at com.my.spring.MyApplication.onStartup(MyApplication.java:40)
    at org.springframework.web.SpringServletContainerInitializer.onStartup(SpringServletContainerInitializer.java:171)
    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5120)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
    ... 42 more

Caused by: java.lang.IllegalStateException: Attribute 'javax.websocket.server.ServerContainer' not found in ServletContext
    at org.springframework.util.Assert.state(Assert.java:73)
    at org.springframework.web.socket.server.standard.ServletServerContainerFactoryBean.afterPropertiesSet(ServletServerContainerFactoryBean.java:117)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1804)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1741)
    ... 63 more

更新:

移除 Bean 后,一切又恢复正常。 但这不是选择,因为我需要增加消息限制。 还有其他方法吗?

    @Bean
    public ServletServerContainerFactoryBean createWebSocketContainer() {
        ServletServerContainerFactoryBean container = new ServletServerContainerFactoryBean();
        container.setMaxTextMessageBufferSize(1024 * 1024 * 5);
        container.setMaxBinaryMessageBufferSize(1024 * 1024 * 5);
        return container;
    }

【问题讨论】:

    标签: java spring spring-boot tomcat spring-websocket


    【解决方案1】:

    尝试做类似的事情来配置消息大小:

    @Configuration
    @EnableWebSocketMessageBroker
    public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
    
        ...
    
        @Override
        public void configureWebSocketTransport(WebSocketTransportRegistration registration) {
            registration.setMessageSizeLimit(3184700); // default : 64 * 1024
            registration.setSendTimeLimit(20 * 10000); // default : 10 * 10000
            registration.setSendBufferSizeLimit(3 * 512 * 1024); // default : 512 * 1024
    
        }
    }
    

    【讨论】:

      【解决方案2】:

      spring boot 更新后也有同样的问题,如果我们显式配置 ServletServerContainerFactoryBean 的话,看起来我们也需要提供 websocket servlet bean。

      尝试添加:

      @Bean
      public TomcatWebSocketServletWebServerCustomizer tomcatWebSocketServletWebServerCustomizer() {
          return new TomcatWebSocketServletWebServerCustomizer();
      }
      

      为我工作。

      【讨论】:

        最近更新 更多