springboot与vue 集成 websocket方法

14 篇文章 0 订阅
6 篇文章 1 订阅

 Java代码:


import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.*;

/**
 * @author zhangzg
 * @ClassName: TicketWebSocket
 * @Description: 用来推送消息
 * @date 2018/8/16 10:55
 */
@ServerEndpoint("/websocket/{userId}")
@Component
@Slf4j
public class TicketWebSocket {

    //用来存放当前连接的session
    private Session session;
    //key为userId,value为Set<Session>
    private static Map<String, Set<Session>> sessionPool = new HashMap<String, Set<Session>>();
    //key为Session的id,value为userId
    private static Map<String, String> sessionIds = new HashMap<String, String>();

    /**
     * @Description: 用户连接时触发,将userId与session存进map,session存进Set
     * @param: [session, userId]
     * @return: void
     * @auther: zhangzg
     * @date: 2018/8/17 9:22
     */
    @OnOpen
    public void onOpen(Session session, @PathParam(value = "userId") String userId) {
        this.session = session;
        Set<Session> sessions = new HashSet<Session>();
        if (sessionPool.get(userId) != null) {
            sessions = sessionPool.get(userId);
        }
        sessions.add(session);
        sessionPool.put(userId, sessions);
        sessionIds.put(session.getId(), userId);
        log.debug("user:" + userId + "session:" + session.getId() + "连接成功");
    }

    /**
     * @Description: 收到消息时触发
     * @param: [message]
     * @return: void
     * @auther: zhangzg
     * @date: 2018/8/17 9:23
     */
    @OnMessage
    public void onMessage(String message) {
        System.out.println("当前发送人sessionid为" + session.getId() + "内容:" + message);
//        System.out.println("当前发送人sessionid为" + session.getId() + "标题:" + message.getTitle()+"内容:"+message.getContent());
    }

    /**
     * @Description: 连接关闭时触发,从map中移除session与userId
     * @param: []
     * @return: void
     * @auther: zhangzg
     * @date: 2018/8/17 9:24
     */
    @OnClose
    public void onClose() {
        log.debug("sessionId为" + session.getId() + "的关闭");
        //从中取出userId
        String userId = sessionIds.get(session.getId());
        //根据userId找到对应Set,再从Set中移除该Session
        Set<Session> sessions = sessionPool.get(userId);
        if (sessions != null) {
            sessions.remove(session);
        }
        //覆盖原来的sessionPool中的数据
        sessionPool.put(userId, sessions);
        sessionIds.remove(session.getId());
    }

    /**
     * 发生错误时触发
     *
     * @param session
     * @param error
     */
    @OnError
    public void onError(Session session, Throwable error) {
        log.error("webSocket发生错误");
        error.printStackTrace();
        log.debug("sessionId为" + session.getId() + "的webSocket关闭");
        //从中取出userId
        String userId = sessionIds.get(session.getId());
        //根据userId找到对应Set,再从Set中移除该Session
        Set<Session> sessions = sessionPool.get(userId);
        if (sessions != null) {
            sessions.remove(session);
        }
        //覆盖原来的sessionPool中的数据
        sessionPool.put(userId, sessions);
        sessionIds.remove(session.getId());
    }

    /**
     * @Description: 发送消息的方法,若用户不在线则不发送
     * @param: [message, userId]
     * @return: void
     * @auther: zhangzg
     * @date: 2018/8/17 9:27
     */
    public static void sendMessage(TicketMessage message, String userId) {
        Set<Session> sessions = sessionPool.get(userId);
        if (sessions != null) {
            for (Session s : sessions) {
                try {
                    System.out.println(JSON.toJSON(message));
                    s.getBasicRemote().sendText(JSON.toJSON(message).toString());
                } catch (IOException e) {
                    log.error("IOException异常,发送信息失败");
                    e.printStackTrace();
                }
            }
        } else {
            log.debug("session中不存在userId为" + userId + "的用户");

        }
    }

    /**
     * @Description: 返回当前的在线用户数
     * @param: []
     * @return: int
     * @auther: zhangzg
     * @date: 2018/8/17 9:32
     */
    public static int getOnlineNum() {
        return sessionPool.size();
    }

    /**
     * @Description: 返回在线的所有用户的userId,返回结果以“,”隔开
     * @param: []
     * @return: java.lang.String
     * @auther: zhangzg
     * @date: 2018/8/17 9:34
     */
    public static String getOnlineUsers() {
        StringBuffer users = new StringBuffer();
        for (String key : sessionIds.keySet()) {
            users.append(sessionIds.get(key) + ",");
        }
        return users.toString();
    }

    /**
     * @Description: 给在线的所有用户推送msg
     * @param: [msg]
     * @return: void
     * @auther: zhangzg
     * @date: 2018/8/17 9:36
     */
    public static void sendAll(TicketMessage msg) {
        for (String key : sessionIds.keySet()) {
            sendMessage(msg, sessionIds.get(key));
        }
    }

    /**
     * @Description: 给persons当中的用户发送msg
     * @param: [msg, persons]
     * @return: void
     * @auther: zhangzg
     * @date: 2018/8/17 9:37
     */
    public static void SendMany(TicketMessage msg, Set<String> persons) {
        for (String userId : persons) {
            sendMessage(msg, userId);
        }
    }

    /**
     * @Description: 判断用户是否在线
     * @param: [userId]
     * @return: boolean
     * @auther: zhangzg
     * @date: 2018/8/21 15:33
     */
    public static boolean isOnline(String userId) {

        if (sessionPool.get(userId) != null) {
            log.debug("userId" + userId + "在线");
            return true;
        }
        log.debug("userId" + userId + "不在线");
        return false;
    }

}

Vue代码:

只用了initWs()方法和心跳检测方法,其他的可以作为参考

<template>
    <!-- <Card>
        <div>
            <Button type="primary" @click="threadPoxi()" icon="plus">发送消息</Button>
            <Button type="primary" @click="sendMessageByJava()" icon="plus">发送消息使用后台方法</Button>
        </div>
    </Card> -->
</template>

<script>
	import { baseURL, sendMessage } from '@/api/api'
    export default {
        name: "TicketWebSocket",
        data () {
            return {
                user:{},
                userId:'',
                websocket: null,
                msg:{
                    msgTitle: '12123',
                    content: '1325154564',
                    sender: '',
                    receiver: '6',
                    bussinessId: '1'
                },
                errorTaskFlag:false,
                websocket_connected_count: 0,
                timeout: 7100000, // 2小时发一次心跳,比server端设置的连接时间稍微小一点,在接近断开的情况下以通信的方式去重置连接时间。
                serverTimeoutObj: null
            }
        },
        methods: {
            sendMessageByJava(){
                let params={
                    msgTitle: this.msg.msgTitle,
                    content: this.msg.content,
                    sender: '6',
                    receiver: this.msg.receiver,
                    bussinessId: this.msg.bussinessId
                };
                sendMessage(params).then((res) =>{
                    // console.log("到这而了");
                    console.log(res.data.resultData)
                })
            },
            threadPoxi(){  // 实际调用的方法 如果ws已经连接则直接发送消息;如正在开启状态,则等待300毫秒,再发送消息;若未开启 ,则等待500毫秒,再发送消息。
                // 参数
                const agentData = "从前台发出的信息";
                //若是ws开启状态
                if (this.websocket.readyState === this.websocket.OPEN) {
                    this.websocketsend(agentData)
                }
                // 若是 正在开启状态,则等待300毫秒
                else if (this.websocket.readyState === this.websocket.CONNECTING) {
                    let that = this;//保存当前对象this
                    setTimeout(function () {
                        that.websocketsend(agentData)
                    }, 300);
                }
                // 若未开启 ,则等待500毫秒
                else {
                    this.initWs();
                    let that = this;//保存当前对象this
                    setTimeout(function () {
                        that.websocketsend(agentData)
                    }, 500);
                }
            },
            initWs () {
                // websocket连接
                // let websocket_connected_count = 0;
                let onclose_connected_count = 0;

                if ('WebSocket' in window) {
                    let ws = 'ws://';
                    if(window.location.protocol == 'https:') ws = 'wss://';
                    this.websocket = new WebSocket(ws + baseURL.split("://")[1] + "/websocket/" + JSON.parse(localStorage.getItem('userFront')).orgUser.id);
                }
                else {
                    alert('Sorry, websocket not supported by your browser.')
                }
                //数据接收
                // this.websocket.onmessage = this.websocketonmessage;

                // 连接成功建立的回调方法
                this.websocket.onopen = (e) => {
                    clearInterval(this.serverTimeoutObj);
                    this.heartCheck();
                    this.errorTaskFlag = false;
                    // console.log("连接成功")
                };
                // 连接发生错误,连接错误时会继续尝试发起连接(5秒重试一下)
                this.websocket.onerror = () => {
                    // console.log("onerror连接发生错误");
                        setTimeout(() => {
                            this.initWs()
                        },5000)
                };
                // 接受到消息的回调方法
                this.websocket.onmessage = (e) => {
                    // console.log("接受到消息了");
                    let message = e.data;
                    if(message){
                        //执行接收到消息的操作,一般是刷新UI
                    }
                    this.$Notice.info({
                        title: '你有一条新的消息!'
                    });
                    this.$emit('new-message','msg');
                    this.$store.commit("refreshMsg", true);
                    this.$store.commit("freshMsgList", true);
                };

                // 接受到服务端关闭连接时的回调方法
                this.websocket.onclose = () => {
                    // console.log("关闭了");
                    // Tip("onclose断开连接");
                }
            },
            // 心跳检测, 每隔一段时间检测连接状态,如果处于连接中,就向server端主动发送消息,来重置server端与客户端的最大连接时间,如果已经断开了,发起重连。
            heartCheck() {
                this.serverTimeoutObj = setInterval(() => {
                    if(this.websocket && this.websocket.readyState && this.websocket.readyState === 1){
                        const currentDate = new Date();
                        const hour = currentDate.getHours() < 10 ? '0'+currentDate.getHours() : currentDate.getHours();
                        const minute = currentDate.getMinutes() < 10 ? '0'+currentDate.getMinutes() : currentDate.getMinutes();
                        const seconds = currentDate.getSeconds() < 10 ? '0'+currentDate.getSeconds() : currentDate.getSeconds();
                        // console.log("连接状态,发送消息保持连接" + `${hour}:${minute}:${seconds}`);
                        this.websocket.send("ping");
                    }else{
                        // console.log("断开状态,尝试重连");
                        this.initWs();
                    }
                }, this.timeout)
            }


        },
        created(){
            this.initWs();
        },
        beforeDestroy() {
            clearInterval(this.serverTimeoutObj);
            this.websocket.close();
        }
    }
</script>

<style scoped>

</style>

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值