欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

websocket在springboot+vue中的使用

程序员文章站 2022-05-18 21:04:59
1、websocket在springboot中的一种实现 在java后台中,websocket是作为一种服务端配置,其配置如下 加入上面的配置之后就可以编辑自己的websocket实现类了,如下 到此后台服务端的工作已经做好了,前端如何作为客户端进行连接呢,请继续往下看。。 为了实现断开自动重连,我 ......

1、websocket在springboot中的一种实现

  在java后台中,websocket是作为一种服务端配置,其配置如下

@configuration
public class websocketconfig {
  
    @bean(name="serverendpointexporter")
    public serverendpointexporter getserverendpointexporterbean(){
        return new serverendpointexporter();
    }
}

  加入上面的配置之后就可以编辑自己的websocket实现类了,如下

@component
@serverendpoint(value = "/messagesocket/{userid}")
public class messagewebsocket {

    private static final logger logger = loggerfactory.getlogger(messagewebsocket.class);

    /**
     * 静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。
     */
    private static int onlinecount = 0;

    /**
     * key: userid value: sessionids
     */
    private static concurrenthashmap<integer, concurrentlinkedqueue<string>> usersessionmap =  new concurrenthashmap<>();

    /**
     * concurrent包的线程安全map,用来存放每个客户端对应的mywebsocket对象。
     */
    private static concurrenthashmap<string, messagewebsocket> websocketmap = new concurrenthashmap<>();

    /**
     * key: sessionid value: userid
     */
    private static concurrenthashmap<string, integer> sessionusermap = new concurrenthashmap<>();

    /**
     * 当前连接会话,需要通过它来给客户端发送数据
     */
    private session session;

    /**
     * 连接建立成功调用的方法
     * */
    @onopen
    public void onopen(session session, @pathparam("userid") integer userid) {
        system.out.println(applicationcontext);
        try {
            this.session = session;
            string sessionid = session.getid();
            //建立userid和sessionid的关系
            if(usersessionmap.containskey(userid)) {
                usersessionmap.get(userid).add(sessionid);
            }else{
                concurrentlinkedqueue<string> queue = new concurrentlinkedqueue<>();
                queue.add(sessionid);
                usersessionmap.put(userid, queue);
            }
            sessionusermap.put(sessionid, userid);
            //建立sessionid和websocket引用的关系
            if(!websocketmap.containskey(sessionid)){
                websocketmap.put(sessionid, this);
                addonlinecount();           //在线数加1
            }
        }catch (exception e){
            logger.error("连接失败");
            string es = exceptionutils.getfullstacktrace(e);
            logger.error(es);
        }
    }

    /**
     * 连接关闭调用的方法
     */
    @onclose
    public void onclose() {
        string sessionid = this.session.getid();
        //移除userid和sessionid的关系
        integer userid = sessionusermap.get(sessionid);
        sessionusermap.remove(sessionid);
        if(userid != null) {
            concurrentlinkedqueue<string> sessionids = usersessionmap.get(userid);
            if(sessionids != null) {
                sessionids.remove(sessionid);
                if (sessionids.size() == 0) {
                    usersessionmap.remove(userid);
                }
            }
        }
        //移除sessionid和websocket的关系
        if (websocketmap.containskey(sessionid)) {
            websocketmap.remove(sessionid);
            subonlinecount();           //在线数减1
        }
    }

    /**
     * 收到客户端消息后调用的方法
     *
     * @param messagestr 客户端发送过来的消息
     **/
    @onmessage
    public void onmessage(string messagestr, session session, @pathparam("userid") integer userid) throws ioexception {
   
    }

    /**
     *
     * @param session
     * @param error 当连接发生错误时的回调
     */
    @onerror
    public void onerror(session session, throwable error) {
        string es = exceptionutils.getfullstacktrace(error);
        logger.error(es);
    }


    /**
     * 实现服务器主动推送
     */
    public void sendmessage(string message, integer touserid) throws ioexception {
        if(touserid != null && !stringutil.isempty(message.trim())){
            concurrentlinkedqueue<string> sessionids = usersessionmap.get(touserid);
            if(sessionids != null) {
                for (string sessionid : sessionids) {
                    messagewebsocket socket = websocketmap.get(sessionid);
                    socket.session.getbasicremote().sendtext(message);
                }
            }
        }else{
            logger.error("未找到接收用户连接,该用户未连接或已断开");
        }
    }

    public void sendmessage(string message, session session) throws ioexception {
        session.getbasicremote().sendtext(message);
    }

     /**
    *获取在线人数
    */
    public static synchronized int getonlinecount() {
        return onlinecount;
    }
     /**
    *在线人数加一
    */
    public static synchronized void addonlinecount() {
        messagewebsocket.onlinecount++;
    }
    /**
    *在线人数减一
    */
    public static synchronized void subonlinecount() {
        messagewebsocket.onlinecount--;
    }
}

到此后台服务端的工作已经做好了,前端如何作为客户端进行连接呢,请继续往下看。。

为了实现断开自动重连,我们使用的reconnecting-websocket.js组件

//websocket连接实例
let websocket = null;

//初始话websocket实例
function initwebsocket(userid) {
    // ws地址 -->这里是你的请求路径
    let host = urlconfig.wsurl +  'messagesocket/' + userid;
    if ('websocket' in window) {
        websocket = new reconnectingwebsocket(host);
        // 连接错误
        websocket.onerror = function () {
        }

        // 连接成功
        websocket.onopen = function () {
        }

        // 收到消息的回调,e.data为收到的信息
        websocket.onmessage = function (e) {
        }

        // 连接关闭的回调
        websocket.onclose = function () {
        }
        
        //监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
        window.onbeforeunload = function () {
            closewebsocket();
        }
    } else {
        alert('当前浏览器不支持websocket')
        return;
    }
}

//关闭websocket连接
function closewebsocket() {
    websocket.close();
}

//发送消息
function sendmessage(message){
   websocket.send(message);
}

至此一个简易的完整的websocket已经完成了,具体功能可以依此为基本进行扩展。