Spring Boot 整合 WebSocket 使用记录

本文记录了使用Spring Boot实现WebSocket的过程,包括客户端javascript前端实现和服务器端java后台的详细步骤。同时,文章列举并解决了在WebSocket服务端获取HttpSession、项目打jar包异常、Nginx转发配置以及心跳超时等问题,提供了相应的解决方案和参考资料。
摘要由CSDN通过智能技术生成

前言

由于项目需要定时将消息从Web端推送至客户端
通常使用的方式有:AJAX轮询、XHR长轮询、iframe、Comet、websocket等

部分详情可见:https://blog.csdn.net/qq_43225978/article/details/105396640

考虑实现的难度及复杂度,最终选用WebSocket方式。

WebSocket 简介

WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议。

WebSocket 使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在 WebSocket API 中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。

在 WebSocket API 中,浏览器和服务器只需要做一个握手的动作,然后,浏览器和服务器之间就形成了一条快速通道。两者之间就直接可以数据互相传送。

现在,很多网站为了实现推送技术,所用的技术都是 Ajax 轮询。轮询是在特定的的时间间隔(如每1秒),由浏览器对服务器发出HTTP请求,然后由服务器返回最新的数据给客户端的浏览器。这种传统的模式带来很明显的缺点,即浏览器需要不断的向服务器发出请求,然而HTTP请求可能包含较长的头部,其中真正有效的数据可能只是很小的一部分,显然这样会浪费很多的带宽等资源。

HTML5 定义的 WebSocket 协议,能更好的节省服务器资源和带宽,并且能够更实时地进行通讯。

在这里插入图片描述

浏览器通过 JavaScript 向服务器发出建立 WebSocket 连接的请求,连接建立以后,客户端和服务器端就可以通过 TCP 连接直接交换数据。

当你获取 Web Socket 连接后,你可以通过 send() 方法来向服务器发送数据,并通过 onmessage 事件来接收服务器返回的数据。

以下 API 用于创建 WebSocket 对象。

WebSocket 简介及API
https://www.runoob.com/html/html5-websocket.html
http://www.ruanyifeng.com/blog/2017/05/websocket.html
https://developer.mozilla.org/zh-CN/docs/Web/API/WebSocket

WebSocket 客户端(javascript前端)实现

javascript 实现

// 心跳重试连接次数
var websocket_reconnected_count = 0;
var websocket = null;
// 初始化WebSocket连接
function initWebSocket() {
   
    websocket = null;
    // 判断当前环境是否支持websocket
    if(window.WebSocket){
   
        if(!websocket){
   
        	// 获取协议类型
            var protocol = window.location.protocol;
            // console.info(protocol)
            // 通过访问协议类型,判断使用的websocket协议类型
            var ws_url = protocol=='http:'?'ws://':'wss://'
            // 获取域名
            var host = window.location.host;
            // 获取端口号
            var port = window.location.port;
            // 获取项目访问路由
            var pathName = window.location.pathname;
            // 截取项目名
            var projectName = pathName.substring(0, pathName.substr(1).indexOf('/') + 1);
            // 拼接websocket访问地址
            ws_url += host + projectName + "/webSocket/user_1";
            // console.info(ws_url);
            // 创建websocket对象
            websocket = new WebSocket(ws_url);
        }
    }else{
   
        var content = '【当前浏览器不支持WEBSOCKET,无法获取预警提醒消息,为获得良好的使用体验,推荐您下载使用<a style="color: orange;text-decoration: underline;" target="_blank" href="https://xxx.xxx.com/updown/41_chrome_installer.exe">Chrome浏览器</a>】';
        alter(content);
    }

    //连接成功建立的回调方法
    websocket.onopen = function () {
   
        console.log('WebSocket连接成功');
        // 成功建立连接后,重置心跳检测
        heartCheck.reset().start();
    }
    //连接发生错误的回调方法
    websocket.onerror = function () {
   
        console.log('WebSocket连接发生错误');
    };
    //接收到消息的回调方法
    websocket.onmessage = function (event) {
   
        // console.log("=====WebSocket接收到消息=====");
        // console.log(event);
        // console.log(event.data);
		
		// 当服务端的会话不存在时,返回标志
		if(event.data=="\"sessionIsNulltrue\""){
   
            // 断开ws
            websocket.close();
            // 因为是会话过期,所以心跳重试链接机制的次数websocket_reconnected_count归零
            websocket_reconnected_count=0;
            // 重置清空心跳
            heartCheck.reset();
            // 使用layui弹窗提醒
            parent.layer.open({
   
                content: "会话过期!请重新登录!"
                ,btn: '确定',
                closeBtn : false,
                yes: function(index, layero){
   
                    //按钮【按钮一】的回调
                    // console.info("=======")
                    parent.layer.closeAll();
                    // 跳转至主页
                    window.top.location.href = Common.ctxPath + "/"
                }
            });
        }

        // 如果获取到消息,说明连接是正常的,重置心跳检测
        heartCheck.reset().start();
    }
    //连接关闭的回调方法
    websocket.onclose = function () {
   
        console.log('WebSocket连接关闭');
    }

    //监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
    window.onbeforeunload = function () {
   
        // 关闭WebSocket连接
        websocket.close();
    }
}
// 心跳检测, 每隔一段时间检测连接状态,如果处于连接中,就向server端主动发送消息,来重置server端与客户端的最大连接时间,如果已经断开了,发起重连。
var heartCheck = {
   
 	// 30s 发一次心跳,比server端设置的连接时间稍微小,在接近断开的情况下以通信的方式去重置连接时间。
    timeout: 30000,
    serverTimeoutObj: null,
    reset: function(){
   
	    var self = this;
        clearTimeout(self.timeout);
        clearInterval(self.serverTimeoutObj);
        return self;
    },
    start: function(){
   
        var self = this;
        this.serverTimeoutObj = setInterval(function(){
   
            if(websocket.readyState == 1){
   
                console.log("连接状态,心跳保持连接");
                websocket.send("ping");
                heartCheck.reset().start();    // 如果获取到消息,说明连接是正常的,重置心跳检测
            }else{
   
                if(websocket_reconnected_count>0){
   
                   --websocket_reconnected_count;
                    console.log
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值