【问题标题】:Using Java API for WebSocket (JSR-356) with Spring Boot在 Spring Boot 中使用 Java API for WebSocket (JSR-356)
【发布时间】:2014-10-12 22:45:18
【问题描述】:

我是 Spring 新手(并且在 stackoverflow 上提问)。

我想通过 Spring Boot 启动嵌入式 (Tomcat) 服务器并向其注册 JSR-356 WebSocket 端点。

这是主要的方法:

@ComponentScan
@EnableAutoConfiguration
public class Server {
    public static void main(String[] args) {
        SpringApplication.run(Server.class, args);
    }
}

这是配置的样子:

@Configuration
public class EndpointConfig {

    @Bean
    public EchoEndpoint echoEndpoint() {
        return new EchoEndpoint();
    }

    @Bean
    public ServerEndpointExporter endpointExporter() {
        return new ServerEndpointExporter();
    } 
}

EchoEndpoint 的实现很简单:

@ServerEndpoint(value = "/echo", configurator = SpringConfigurator.class)
public class EchoEndpoint {

    @OnMessage
    public void handleMessage(Session session, String message) throws IOException {
        session.getBasicRemote().sendText("echo: " + message);
    }
}

对于第二部分,我关注了这篇博文:https://spring.io/blog/2013/05/23/spring-framework-4-0-m1-websocket-support

但是,当我运行应用程序时,我得到:

Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'endpointExporter' defined in class path resource [hello/EndpointConfig.class]: Initialization of bean failed; nested exception is java.lang.IllegalStateException: Failed to get javax.websocket.server.ServerContainer via ServletContext attribute

该异常进一步是由ServerEndpointExporter 中的NullPointerException 引起的,因为此时applicationContext 上的getServletContext 方法仍返回null

有对 Spring 有更深入了解的人可以帮帮我吗?谢谢!

【问题讨论】:

    标签: java spring websocket spring-boot jsr356


    【解决方案1】:

    ServerEndpointExporter 对应用程序上下文的生命周期做出了一些假设,当您使用 Spring Boot 时这些假设不成立。具体来说,假设当调用setApplicationContext 时,在该ApplicationContext 上调用getServletContext 将返回一个非空值。

    您可以通过替换来解决该问题:

    @Bean
    public ServerEndpointExporter endpointExporter() {
        return new ServerEndpointExporter();
    } 
    

    与:

    @Bean
    public ServletContextAware endpointExporterInitializer(final ApplicationContext applicationContext) {
        return new ServletContextAware() {
    
            @Override
            public void setServletContext(ServletContext servletContext) {
                ServerEndpointExporter serverEndpointExporter = new ServerEndpointExporter();
                serverEndpointExporter.setApplicationContext(applicationContext);
                try {
                    serverEndpointExporter.afterPropertiesSet();
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }               
            }           
        };
    }
    

    这会延迟处理,直到 servlet 上下文可用。

    更新:您可能想观看SPR-12109。修复后,上述解决方法将不再需要。

    【讨论】:

    • 完美运行。感谢您的精彩回答!
    • 在 2018 年,不再需要解决方法,但问题帮助很大。我在其他任何地方都找不到完整的例子……干杯!!!
    • 我正在使用 Spring Boot 2.1.0.RELEASE 和 Java 11 和 Tomcat 9 将 WAR 部署到 tomcat webapp 中,但仍然看到相同的错误。
    猜你喜欢
    • 1970-01-01
    • 2014-11-04
    • 2017-07-20
    • 1970-01-01
    • 1970-01-01
    • 2013-10-13
    • 2015-05-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多