美文网首页
Spring boot集成Websocket,前端心跳机制实现

Spring boot集成Websocket,前端心跳机制实现

作者: 小偷阿辉 | 来源:发表于2019-05-15 15:04 被阅读0次

1.引入websocket依赖

 <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-websocket</artifactId>
      <version>2.0.5.RELEASE</version>
    </dependency>

2.将websocket相关服务交给spring管理

public class MySpringConfigurator extends ServerEndpointConfig.Configurator implements ApplicationContextAware {
    private static volatile ApplicationContext context;

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

    @Override
    public <T> T getEndpointInstance(Class<T> clazz) throws InstantiationException {
        return context.getBean(clazz);
    }
}

3.websocket配置

@Configuration
@ConditionalOnWebApplication
public class WebSocketConfig {
    /**
     * 注入对象ServerEndpointExporter,这个bean会自动注册使用了@ServerEndpoint注解声明的Websocket endpoint
     */
    @Bean
    public ServerEndpointExporter getServerEndpointExporter(){
        return new ServerEndpointExporter();
    }
    @Bean
    public MySpringConfigurator getSpringConfigurator(){
        return new MySpringConfigurator();
    }
}

4.配置WebSocketEndPoint(其实就是配置Controller差不多,支持restApi)

@Component
@ServerEndpoint(value = "/mywebsocket/{openId}",configurator = MySpringConfigurator.class)
public class MyWebSocketEndPoint {
    //当前会话
    private Session session;
    private static int onlineCount;
    private static Map<String,MyWebSocketEndPoint> webSocketEndPointMap=new ConcurrentHashMap<String,MyWebSocketEndPoint>();
    @OnOpen
    public void onOpen(@PathParam(value="openId") String openId , @PathParam(value="role") String role , Session session){
        if( webSocketEndPointMap.containsKey(openId)){
            MyWebSocketEndPoint myWebSocketEndPoint=webSocketEndPointMap.get(openId);
            this.session=myWebSocketEndPoint.session;
            return;
        }
        webSocketEndPointMap.put("openId",this);
        this.session=session;
        this.addOnlineCount();
    }
    @OnClose
    public void onClose(Session session){
        webSocketEndPointMap.remove(this);
        this.subOnlineCount();
    }
    @OnError
    public void onError(Throwable throwable,Session session){
        System.err.println("error heppenning");
        throwable.printStackTrace();
    }
    @OnMessage
    public void onMessage(String msg){
        System.out.println(msg);
        sendMsg(msg);
    }
    private void sendMsg(String msg){
        try {
            session.getBasicRemote().sendText(msg);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    public static synchronized int getOnlineCount(){
        return onlineCount;
    }
    public static synchronized void addOnlineCount(){
        onlineCount++;
    }
    public static synchronized void subOnlineCount(){
        onlineCount--;
    }
}

5.前端配置

          var lockReconnect = false;//避免重复连接
            var wsUrl =  "ws://192.168.3.207:80/mywebsocket/{aaaa}";
            var ws;
            createWebSocket();
            function createWebSocket() {
                try {
                    ws = new WebSocket(wsUrl);
                    init();
                } catch(e) {
                    alert("it error");
                    console.log('catch'+e);
                    reconnect(wsUrl);
                }
            }

            function init() {

                ws.onclose = function () {
                    console.log('链接关闭');
                    reconnect(wsUrl);
                };
                ws.onerror = function() {
                    console.log('发生异常了');
                    reconnect(wsUrl);
                };
                ws.onopen = function () {
                    console.log('建立连接');
                    ws.send(JSON.stringify({"doWhat":"getLink"}));
                    //心跳检测重置
                    heartCheck.start();
                };
                ws.onmessage = function (event) {
                    console.log('接收到消息'+event.data);
                    heartCheck.start();
                    //拿到任何消息都说明当前连接是正常的
                }
            }

            var lockReconnect = false;//避免重复连接
            function reconnect(url) {
                if(lockReconnect) {
                    return;
                };
                lockReconnect = true;
                //没连接上会一直重连,设置延迟避免请求过多
                tt && clearTimeout(tt);
                tt = setTimeout(function () {
                    createWebSocket(url);
                    lockReconnect = false;
                }, 40000);
            }
            //心跳检测
            var heartCheck = {
                timeout: 60000,
                timeoutObj: null,
                serverTimeoutObj: null,
                start: function(){
                    console.log('start');
                    var self = this;
                    this.timeoutObj && clearTimeout(this.timeoutObj);
                    this.serverTimeoutObj && clearTimeout(this.serverTimeoutObj);
                    this.timeoutObj = setTimeout(function(){
                        //这里发送一个心跳,后端收到后,返回一个心跳消息,
                        //onmessage拿到返回的心跳就说明连接正常
                        console.log('55555');
                        ws.send(JSON.stringify({"doWhat":"testLink"}));
                        self.serverTimeoutObj = setTimeout(function() {
                            console.log(111);
                            console.log(ws);
                            ws.close();
                            // createWebSocket();
                        }, self.timeout);
                    }, this.timeout)
                }
            }

相关文章

网友评论

      本文标题:Spring boot集成Websocket,前端心跳机制实现

      本文链接:https://www.haomeiwen.com/subject/hqvpaqtx.html