若依二次开发WebSocket实战

1. 添加WebSocket依赖

在ruoyi-framework/pom.xml中添加Spring Boot WebSocket的依赖:

<!-- SpringBoot Websocket -->
<dependency>  
   <groupId>org.springframework.boot</groupId>  
   <artifactId>spring-boot-starter-websocket</artifactId>  
</dependency>

2.在ruoyi-framework中创建一个WebSocketConfig配置类,如下所示:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
 
/**
 * 开启WebSocket支持
 */
@Configuration
public class WebSocketConfig {
    @Bean
    public ServerEndpointExporter serverEndpointExporter() {
        return new ServerEndpointExporter();
    }
}

3、在ruoyi-framework中创建一个WebSocketServer控制器类,用于处理WebSocket连接和消息

这个类主要用于使用创建连接、监听消息和发送消息等

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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.concurrent.CopyOnWriteArraySet;
 
// @ServerEndpoint 声明并创建了webSocket端点, 并且指明了请求路径
// id 为客户端请求时携带的参数, 用于服务端区分客户端使用
@ServerEndpoint("/ws/{sid}")
@Component
public class WebSocketServer {
 
    // 日志对象
    private static final Logger log = LoggerFactory.getLogger(WebSocketServer.class);
 
    // 静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。
    private static int onlineCount = 0;
 
    // concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。
    private static CopyOnWriteArraySet<WebSocketServer> webSocketSet = new CopyOnWriteArraySet<>();
    // private static ConcurrentHashMap<String,WebSocketServer> websocketList = new ConcurrentHashMap<>();
 
    // 与某个客户端的连接会话,需要通过它来给客户端发送数据
    private Session session;
 
    // 接收sid
    private String sid = "";
 
    /*
     * 客户端创建连接时触发
     * */
    @OnOpen
    public void onOpen(Session session, @PathParam("sid") String sid) {
        this.session = session;
        webSocketSet.add(this); // 加入set中
        addOnlineCount(); // 在线数加1
        log.info("有新窗口开始监听:" + sid + ", 当前在线人数为" + getOnlineCount());
        this.sid = sid;
        try {
            sendMessage("连接成功");
        } catch (IOException e) {
            log.error("websocket IO异常");
        }
    }
 
    /**
     * 客户端连接关闭时触发
     **/
    @OnClose
    public void onClose() {
        webSocketSet.remove(this); // 从set中删除
        subOnlineCount(); // 在线数减1
        log.info("有一连接关闭!当前在线人数为" + getOnlineCount());
    }
 
    /**
     * 接收到客户端消息时触发
     */
    @OnMessage
    public void onMessage(String message, Session session) {
        log.info("收到来自窗口" + sid + "的信息:" + message);
        // 群发消息
        for (WebSocketServer item : webSocketSet) {
            try {
                item.sendMessage(message);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
 
    /**
     * 连接发生异常时候触发
     */
    @OnError
    public void onError(Session session, Throwable error) {
        log.error("发生错误");
        error.printStackTrace();
    }
 
    /**
     * 实现服务器主动推送(向浏览器发消息)
     */
    public void sendMessage(String message) throws IOException {
        log.info("服务器消息推送:"+message);
        this.session.getBasicRemote().sendText(message);
    }
 
    /**
     * 发送消息到所有客户端
     * 指定sid则向指定客户端发消息
     * 不指定sid则向所有客户端发送消息
     * */
    public static void sendInfo(String message, @PathParam("sid") String sid) throws IOException {
        log.info("推送消息到窗口" + sid + ",推送内容:" + message);
        for (WebSocketServer item : webSocketSet) {
            try {
                // 这里可以设定只推送给这个sid的,为null则全部推送
                if (sid == null) {
                    item.sendMessage(message);
                } else if (item.sid.equals(sid)) {
                    item.sendMessage(message);
                }
            } catch (IOException e) {
                continue;
            }
        }
    }
 
    public static synchronized int getOnlineCount() {
        return onlineCount;
    }
 
    public static synchronized void addOnlineCount() {
        WebSocketServer.onlineCount++;
    }
 
    public static synchronized void subOnlineCount() {
        WebSocketServer.onlineCount--;
    }
 
    public static CopyOnWriteArraySet<WebSocketServer> getWebSocketSet() {
        return webSocketSet;
    }
 
}

4、前端页面的配置

<template>
  <!-- 包含音频播放功能的包装元素 -->
  <div id="wrap" v-show="false"> <!-- v-show="false" 隐藏此元素 -->
    <!-- 音频播放控件 -->
    <audio 
      v-if="false" 
      src="@/api/audio/preview.mp3" 
      id="audio" 
      preload="auto" 
      muted 
      autoplay 
      type="audio/mp3" 
      controls="controls"
    >
      <span id="audioId">播放音乐</span>
    </audio>
  </div>
</template>

<script>
export default {
  // 【1】组件创建时初始化 WebSocket 连接
  created() {
    this.initWebSocket();
  },
  // 【2】组件销毁时关闭 WebSocket 连接
  destroyed() {
    this.websock.close(); //离开路由之后断开websocket连接
  },
  // 【3】方法
  methods: {
    // 3.1初始化 WebSocket连接
    initWebSocket() {
      const wsuri = "ws://localhost:8080/ws/123214";  // WebSocket 服务器的 URI
      if (typeof WebSocket === "undefined") {     // 检查浏览器是否支持 WebSocket
        console.log("您的浏览器不支持WebSocket");
      } else {
        console.log(wsuri);
        // 创建 WebSocket 连接
        this.websock = new WebSocket(wsuri); 
        // 设置 WebSocket 各种事件处理函数
        this.websock.onmessage = this.websocketonmessage; // 接收到消息时调用
        this.websock.onopen = this.websocketonopen; // 连接成功时调用
        this.websock.onerror = this.websocketonerror; // 连接错误时调用
        this.websock.onclose = this.websocketclose; // 连接关闭时调用
      }
    },
    // 3.2连接建立之后执行send方法发送数据
    websocketonopen() {
      let actions = { "test": "我已在线" };   // 创建一个消息对象
      this.websocketsend(JSON.stringify(actions));   // 发送 JSON 格式的消息
    },
    // 3.3连接建立失败重连
    websocketonerror() {
      this.initWebSocket();   // 重新初始化 WebSocket 连接
    },
    // 3.4数据接收
    websocketonmessage(e) {
      this.$modal.msg(e.data);   // 显示接收到的消息
      console.log(e.data);   // 打印接收到的消息
      var audio = document.querySelector("audio");   // 获取音频元素 用这种标签名称获取的方式就不会报错了
      audio.currentTime = 0;   // 从头开始播放
      audio.muted = false;   // 取消静音
      audio.play();   // 音频播放
      // const redata = JSON.parse(e.data);   // 可用于解析 JSON 格式的消息(如果需要)
    },
    // 3.5向服务器发送数据
    websocketsend(Data) {
      this.websock.send(Data);   // 使用 WebSocket 连接发送数据
    },
    // 3.6WebSocket 连接关闭时调用
    websocketclose(e) {
      console.log('断开连接', e);   // 打印连接断开的信息
    }
  }
}
</script>

audio是因为业务场景需要引入的,主要是对与来订单提醒的提示音,然后可以在websocketonmessage()接受数据和进行处理

5、SecurityConfig设置匿名访问

这个主要是方便我们测试
请添加图片描述

整体结构(仅供参考)
请添加图片描述

6.运行效果

前端

在这里插入图片描述

后端

在这里插入图片描述

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值