[websocket] 关于使用websocket时遇到的坑

因为websocket是第一次接触,所以遇到的问题很多,需要自己一点一点去踩。

在这里主要说明使用@ServerEndpoint注解方式时遇到的问题以及解决方法

1.启动包类型不同带来的问题

使用的是Springboot框架,所以开发时使用jar包方式运行,这时启动类不需要更改,只需要加一个配置文件,如下:

@Configuration
public class WebSocketConfig {

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

这样就可以使用websocket了。

但由于线上使用docker部署的,而且使用的是war包,所以这时就要把jar改成war,怎么改的这里就不赘述了,只需要改一下启动类就行。网上很多资料,我也是照着网上的步骤改的,然后用外置的tomcat启动,注意是外置的,问题来了,报错,如下:

Caused by: java.lang.IllegalStateException: javax.websocket.server.ServerContainer not available
	at org.springframework.util.Assert.state(Assert.java:70)
	at org.springframework.web.socket.server.standard.ServerEndpointExporter.afterPropertiesSet(ServerEndpointExporter.java:102)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1689)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1627)
	... 63 common frames omitted

报了个websocket的服务器容器不可用。于是我到网上查了一下,但没找到。然后我就去查是不是jar问题,发现也没冲突。想了很久,也查找了很多网站也没找到,突然想到是不是注解的问题,就去看了这个@ServerEndpoint是哪个jar包的,发现是tomcat相关包下面的,这样问题就找到了,之前我们jar包启动,需要配置一个ServerEndpointExporter,这个配置的目的就是把找到@ServerEndpoint注解的bean,交给Spring管理,但是现在,我们使用tomcat启动,自然不需要在配置了,直接交由tomcat容器管理。然后把这个配置注释掉,在启动tomcat,可以正常启动。

2.websocket handle类注入问题

使用websocket时,一般是写一个handle类用来接收或发送消息,也就是配置@OnOpen、@OnMessage、@OnError等注解的。

因为要处理业务,所以要注入一些服务,但是用@Autowrited、@Resource、@Component等等都不起作用。所以在这里提供一种新的方法,手动注入

将这个handle类实现ApplicationContextAware接口,然后重写setApplicationContext方法。如下:

@ServerEndpoint("/ws")
@Component
public class MyWebsocketHandle implements ApplicationContextAware {

    /**
     * 定义applicationContext
     */
    private static ApplicationContext applicationContext;

    /**
     * 要注入的业务接口
     */
    private WebsocketAdapter websocketAdapter;
    

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        MyWebsocketHandle.applicationContext = applicationContext;
    }

    private void init(){
        if (websocketAdapter == null){
            synchronized (MyWebsocketHandle.class){
                if (websocketAdapter == null){
                    websocketAdapter = applicationContext.getBean(WebsocketAdapter.class);
                }
            }
        }
    }
}

自定义ApplicationContext也可在启动类中创建,启动时直接指定定义的类。如果使用tomcat部署的话在启动类中可能会有问题。

上面用到了双检锁,也可以根据自身业务情况使用其他单例的设计模式。

以上是使用tomcat包中注解的方式,用Spring集成的websocket也可以,有时间会写一下用那种方法时遇到的坑。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值