SpringBoot+WebSocket问题:Failed to register @ServerEndpoint class

项目中用到了WebSocket,在开发时没有问题,但是部署到测试服务器时却出现了问题。

  • 环境信息
    • SpringBoot 2.3.1.RELEASE
    • Tomcat 9.0
  • 异常信息
Caused by: java.lang.IllegalStateException: Failed to register @ServerEndpoint
...
Caused by: javax.websocket.DeploymentException: Multiple Endpoints may not be deployed to the same path [/ws/xxx]
  • 代码
@Configuration
public class WebsocketConfig {

    @Bean
    public ServerEndpointExporter serverEndpointExporter() {
        return new ServerEndpointExporter();
    }
}
@Component
@ServerEndpoint(value = "/ws/xxx", encoders = { WsEncoder.class })
public class WebSocket {

    @OnOpen
    public void onOpen(Session session) {
    }

    @OnClose
    public void onClose() {
    }

    @OnMessage
    public void onMessage(String message, Session session) {
    }

    @OnError
    public void onError(Session session, Throwable error) {
    }
}

经过对比分析后,发现开发时的容器是SpringBoot内置Tomcat,使用ServerEndpointExporter扫描注册ServerEndpoint,而测试服务器的容器是Tomcat,使用自带jar包中的ServerApplicationConfig扫描注册ServerEndpoint,不同的容器使用不同的扫描机制。所以在开发环境需要注入ServerEndpointExporter,而在测试、生产环境则不需要注入,而是使用Tomcat容器去管理。

  • 修改后代码
@ConditionalOnProperty(name = "spring.profiles.active", havingValue = "dev")
@Configuration
public class WebsocketConfig {

    @Bean
    public ServerEndpointExporter serverEndpointExporter() {
        return new ServerEndpointExporter();
    }   
}
@ConditionalOnClass(value = WebsocketConfig.class)
@Component
@ServerEndpoint(value = "/ws/{token}", encoders = { WsEncoder.class })
public class WebSocket {
    ....
}

你可能感兴趣的:(SpringBoot+WebSocket问题:Failed to register @ServerEndpoint class)