Springboot+Vue 实现websocket推送

1、后端引入依赖

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

2、引入websocket配置

WebSocketConfig.java

/**
 * @auther pxm
 * @date 2023/6/16
 * @description
 */

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;

/**
 * 开启WebSocket支持
 * @author drg
 */
@Configuration
public class WebSocketConfig {
    @Bean
    public ServerEndpointExporter serverEndpointExporter() {
        return new ServerEndpointExporter();
    }
}
WebSocketServer.java(/websocket/** 方法需要加入白名单)

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.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * websocket 服务端
 *
 * @author pxm
 * @return
 * @date 2023/9/12 9:25
 */
@Slf4j
@ServerEndpoint(value = "/websocket/{userId}")
@Component
public class WebSocketServer {

    /**
     * 记录当前在线连接数
     */
    private static AtomicInteger onlineCount = new AtomicInteger(0);

    /**
     * 存放所有在线的客户端 key 为用户Id
     */
    private static Map<String, Session> clients = new ConcurrentHashMap<>();

    /**
     * 连接建立成功调用的方法
     */
    @OnOpen
    public void onOpen(Session session, @PathParam("userId") String userId) {
        if (clients.containsKey(userId)) {
            clients.remove(userId);
            clients.put(userId, session);
        } else {
            onlineCount.incrementAndGet(); // 在线数加1
            clients.put(userId, session);
            //sendMessage("客户端"+userId,session);
        }
    }

    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose(Session session) {
        for (String userId : clients.keySet()) {
            if (clients.get(userId).equals(session)) {
                clients.remove(session);
                onlineCount.decrementAndGet(); // 在线数减1
            }
        }
    }

    /**
     * 收到客户端消息后调用的方法
     *
     * @param message 客户端发送过来的消息
     */
    @OnMessage
    public void onMessage(String message, Session session) {
        log.info("服务端收到客户端[{}]的消息:{}", session.getId(), message);
        //this.sendMessage(message, session);
    }

    @OnError
    public void onError(Session session, Throwable error) {
        log.error("发生错误");
        error.printStackTrace();
    }

    /**
     * 群发消息
     *
     * @param message 消息内容
     */
    public void sendMessage(String message, Session fromSession) {
        for (Map.Entry<String, Session> sessionEntry : clients.entrySet()) {
            Session toSession = sessionEntry.getValue();
            // 排除掉自己
            //if (!fromSession.getId().equals(toSession.getId())) {
            log.info("服务端给客户端[{}]发送消息{}", toSession.getId(), message);
            toSession.getAsyncRemote().sendText(message);
            //}
        }
    }

    /**
     * 群发消息
     *
     * @param message 消息内容
     */
    public static void sendMessage(String message, String id) {

        Session session = clients.get(id);
        if (session != null) {
            log.debug("服务端给客户端[{}]发送消息{}", session.getId(), message);
            try {
                session.getAsyncRemote().sendText(message);
            } catch (Exception e) {
                log.debug("数据发送失败!疑似断开连接", session.getId(), message);
                clients.remove(id);
            }
        }
    }

    /**
     * 根据用户id获取session
     *
     * @param userId
     * @return
     */
    public Session getUserSession(String userId) {
        return clients.get(userId);
    }
}

其中userId参数表示唯一标识符,可以自己定义,用于前端校验

WebSocketUsersjava

import javax.websocket.Session;
import java.io.IOException;
import java.util.Collection;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

/**
 * websocket 客户端用户集
 *
 * @author ruoyi
 */
public class WebSocketUsers
{

    /**
     * 用户集
     */
    private static Map<String, Session> USERS = new ConcurrentHashMap<String, Session>();
    /**
     * 存储用户
     *
     * @param key 唯一键
     * @param session 用户信息
     */
    public static void put(String key, Session session)
    {
        USERS.put(key, session);
    }

    /**
     * 移除用户
     *
     * @param session 用户信息
     *
     * @return 移除结果
     */
    public static boolean remove(Session session)
    {
        String key = null;
        boolean flag = USERS.containsValue(session);
        if (flag)
        {
            Set<Map.Entry<String, Session>> entries = USERS.entrySet();
            for (Map.Entry<String, Session> entry : entries)
            {
                Session value = entry.getValue();
                if (value.equals(session))
                {
                    key = entry.getKey();
                    break;
                }
            }
        }
        else
        {
            return true;
        }
        return remove(key);
    }

    /**
     * 移出用户
     *
     * @param key 键
     */
    public static boolean remove(String key)
    {
        Session remove = USERS.remove(key);
        if (remove != null)
        {
            boolean containsValue = USERS.containsValue(remove);
            return containsValue;
        }
        else
        {
            return true;
        }
    }

    /**
     * 获取在线用户列表
     *
     * @return 返回用户集合
     */
    public static Map<String, Session> getUsers()
    {
        return USERS;
    }

    /**
     * 群发消息文本消息
     *
     * @param message 消息内容
     */
    public static void sendMessageToUsersByText(String message)
    {
        Collection<Session> values = USERS.values();
        for (Session value : values)
        {
            sendMessageToUserByText(value, message);
        }
    }

    /**
     * 发送文本消息
     * @param message 消息内容
     */
    public static void sendMessageToUserByText(Session session, String message)
    {
        if (session != null)
        {
            try
            {
                session.getBasicRemote().sendText(message);
            }
            catch (IOException e)
            {
//                LOGGER.error("\n[发送消息异常]", e);
            }
        }
        else
        {
//            LOGGER.info("\n[你已离线]");
        }
    }

3、发送websocket(传入要发送的消息以及唯一标识)

 WebSocketServer.sendMessage("message",yourId);

 4、vue页面

在create中舒适化websocket(传入与后端一致的唯一标识)

    created() {
            //初始化websocket
            this.initWebSocket(this.$route.query.examId);
        },

在method中写相关方法

 /****************************websocker ****************************************/
            /**
             * @description: 初始化WebSocket连接
             * @author: pxm
             * @modify:
             * @return {*}
             */
            initWebSocket(examId) {
                // 定义websocket的地址 自行更改为自己后端的ip和端口
                const wsuri = "ws://ip:port/websocket/" + examId;
                // 判断当前浏览器是否支持websocket
                if (typeof WebSocket == "undefined") {
                    console.log("您的浏览器不支持WebSocket");
                } else {
                    console.log(wsuri);
                    // 创建websocket实例
                    this.websock = new WebSocket(wsuri);
                    // 监听websocket的message事件
                    this.websock.onmessage = this.websocketonmessage;
                    // 监听websocket的open事件
                    this.websock.onopen = this.websocketonopen;
                    // 监听websocket的error事件
                    this.websock.onerror = this.websocketonerror;
                    // 监听websocket的close事件
                    this.websock.onclose = this.websocketclose;
                }
            },
            /**
             * @description: 连接建立之后执行send方法发送数据
             * @author: pxm
             * @modify:
             * @return {*}
             */
            websocketonopen() {
                // 定义一个actions对象,用于存储测试信息
                let actions = { test: "我已在线" };
                // 将actions对象转换成JSON字符串,并发送到websocket
                this.websocketsend(JSON.stringify(actions));
            },
            /**
             * @description: 连接建立失败重连
             * @author: pxm
             * @modify:
             * @return {*}
             */
            websocketonerror() {
                // 重新初始化
                this.initWebSocket(this.$route.query.examId);
            },
            /**
             * @description: 数据接收(接到请求后,需要后续做的事)
             * @author: pxm
             * @modify:
             * @return {*}
             */
            websocketonmessage(e) {
                console.log(e.data);
                if (e.data) {
                    //根据自己逻辑完善监听后功能
                   doyourmethod();
                }
            },


            /**
             * @description: 数据发送
             * @author: pxm
             * @modify:
             * @param {*} Data 发送数据
             * @return {*}
             */
            websocketsend(Data) {
                this.websock.send(Data);
            },
            /**
             * @description: 关闭
             * @author: pxm
             * @modify:
             * @param {*} e 信息
             * @return {*}
             */
            websocketclose(e) {
                console.log("断开连接", e);
            },

 

 

 

 

  • 13
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值