小编典典

通过Spring Boot将Java API用于WebSocket(JSR-356)

spring-boot

我是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

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

可以更好地了解Spring的人可以帮助我吗?谢谢!


阅读 383

收藏
2020-05-30

共1个答案

小编典典

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

您可以通过以下方法解决此问题:

@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。一旦修复,就不再需要上述解决方法。

2020-05-30