• 利用WebSocket +MQ发送紧急订单消息,并在客户端收到消息的用户的页面自动刷新列表


    背景:在原有通知公告的基础上,把通知公共的推送服务修改为其他业务收到紧急订单发送公告到消息队列MQ,然后在js中创建一个socket去监听公告,收到公告后刷新所有在订单页面的用户的页面列表(重点就是用户在收到紧急订单时能及时刷新页面并播报语音),语音播报功能可参考我以前的博文,当前功能只是在原有功能的基础上添加接收到公告时刷新列表(刷新列表完成后就会自动播报语音,这是之前已经完成的功能)

    maven依赖:

    1. <dependency>
    2. <groupId>org.springframework.bootgroupId>
    3. <artifactId>spring-boot-starter-websocketartifactId>
    4. dependency>
    5. <dependency>
    6. <groupId>org.springframework.bootgroupId>
    7. <artifactId>spring-boot-starter-amqpartifactId>
    8. dependency>

    注意事项: 一个系统建议只调用一次 creatSocket()方法,否则创建多个 socket实例就最好是创建多个creatSocket()方法,否则多次创建实例都会接收到相同的广播没有意义

    1. WebSocketController.java的修改:

    1. private AmqpTemplate amqpTemplate;
    2.         
    3. @PostMapping("/sendEkanbanYouXian")  //不能在列表刷新的地方触发推送  ,需求页面刷新时发送广播会触发所有人都刷新页面,所有人刷新又会触发所有人再次发送广播,因此造成死循环
    4. public String sendEkanbanYouXian(String msg) {
    5.     // 此处进行数据库操作  ----目前省略,待有需要再加进去
    6.     //WebSocketServer.sendInfo(form.getMessage());//只能推送给一台服务器的用户(193/4)
    7.     this.amqpTemplate.convertAndSend("fanout.exchange.msg","", msg); //使用队列给所有用户发送信息
    8.     return "广播推送成功【" + msg + "】";
    9. }

    2. 提交紧急订单的js:

    1. $.post("/socket/sendEkanbanYouXian", {msg: jiajiText}, function(res) { //业务js中把需要广播的消息发送到消息队列
    2.     layer.msg(res);
    3. });

    3.js中创建Socket实例(用于监听广播)

    1. var socket;
    2. function creatSocket(){
    3.     if (typeof (WebSocket) == "undefined") {
    4.         console.log("您的浏览器不支持WebSocket");
    5.     } else {
    6.         console.log("您的浏览器支持WebSocket");
    7.         //实现化WebSocket对象,指定要连接的服务器地址与端口  建立连接  
    8.         //等同于socket = new WebSocket("ws://localhost:8083/checkcentersys/websocket/20");  
    9.         var curWwwPath = window.document.location.href;// 当前网址
    10.         // 获取主机地址
    11.         var pathName = window.document.location.pathname;
    12.         var pos = curWwwPath.indexOf(pathName);
    13.         var localhostPath = curWwwPath.substring(0, pos);
    14.         var socketPath = localhostPath.replace('http','ws');
    15.         //用ajax同步取IP
    16.         var serverIP="";
    17.         var clientIP="";
    18.         var postData = {};
    19.                 
    20.         $.ajax({
    21.             type : "get",
    22.             url : "/socket/getServerIp",
    23.             data : postData,
    24.             async: false,
    25.             cache : false,
    26.             success : function(data) {
    27.                 if (data != null) {serverIP = data; }else{alert("取不到ServerIP");}
    28.             },
    29.             error : function(data) { alert("取ServerIP异常!");}
    30.         });
    31.         
    32.         $.ajax({
    33.             type : "get",
    34.             url : "/socket/getClientIp",
    35.             data : postData,
    36.             async: false,
    37.             cache : false,
    38.             success : function(data) {
    39.                 if (data != null) {clientIP = data;} else{alert("取不到ClientIP");}
    40.             },
    41.             error : function(data) {alert("取ClientIP异常!");}
    42.         });
    43.         
    44.         socketPath = "ws://"+serverIP+":8101";    //socketPath = "ws://172.16.183.127:8101";
    45.         var loginUserId = document.getElementById("loginUserId").value;
    46.         socket = new WebSocket(socketPath + "/websocket/" + clientIP + "/" + loginUserId);
    47.         //打开事件  
    48.         socket.onopen = function() {console.log("Socket 已打开");};    
    49.         
    50.         socket.onmessage = function(msg) {//获得消息事件 (监听广播) 
    51.             $("#mteSearchBtn").click();//收到广播触发页面列表的刷新
    52.             if (msg.data != "连接成功" && msg.data !="") {//发现消息进入    开始处理前端触发逻辑
    53.                layer.open({
    54.                     type: 1,
    55.                     offset: 'rt',
    56.                     anim: 'slideDown', // 从上往下(右上角)
    57.                     area: ['30%', '160px'],
    58.                     skin: 'layui-layer-molv',
    59.                     shade: 0.1,
    60.                     shadeClose: true,
    61.                     id: 'ID-demo-layer-direction-t',
    62.                     content: '
      '+msg.data+'
      '
    63.                 });
    64.             }
    65.         };
    66.         //关闭事件  
    67.         socket.onclose = function() {console.log("Socket已关闭");};
    68.         //发生了错误事件  
    69.         socket.onerror = function() {alert("Socket发生了错误");}//此时可以尝试刷新页面
    70.     }

    重点:主要就是监听到广播后,调用页面的搜索按钮,进行从新加载列表
     

    4. 上面的弹出层使用的是layui框架的弹出层,但是不太方便使用thymeleaf设置查看权限(例如我的加急订单只给仓库人员查看,其他人不需要看,因此弹出层我需要设置权限,那就使用原生弹出层):

            4.1 替换上面的JS接收socket的部分(重点就是弹出层的动画效果):

    1. socket.onmessage = function(msg) {//获得消息事件 (监听广播)
    2. if (msg.data != "连接成功" && msg.data !="") {//发现消息进入 开始处理前端触发逻辑
    3. $("#socket").fadeIn(3000);
    4. $("#socketmsg").html(msg.data);
    5. $("#mteSearchBtn").click();//收到消息就立马让页面触发刷新 (物料需求页面列表刷新,页面刷新自然就有语音,因此这个功能因为这句代码导致暂时只能适用于 物料需求页面),$("#mteSearchBtn")必须是这样触发,不能直接写mteSearchBtn.click否则无效
    6. // 开启定时器
    7. function startTimes() {
    8. var i = 10;
    9. var timer = window.setInterval(function() {
    10. console.log('还有' + (--i) + '秒关闭socket广播窗口!');
    11. if (i <= 0) {
    12. window.clearInterval(timer);
    13. console.log('已关闭socket广播窗口!');
    14. $("#socket").fadeOut(3000);
    15. $("#socket").fadeTo("3000", 0.7);
    16. }
    17. }, 1000);
    18. }
    19. startTimes();
    20. }
    21. getOnlineCountJS(); //获取在线人数
    22. };

    4.2 html

    1. "socket" th:if="${session.userpermis == 1 || session.ekanbanruku == 1 || session.ekanbanruku == '1'}">
    2. <input type="hidden" id="sockethidIP" th:value="${serverIp}" />
    3. <div id="socketTitle">消息通知
    4. <span id ="socketClose">
    5. <img onclick="hideSocketDialog();" alt="" src="css/images/close.png">
    6. span>
    7. div>
    8. <div id = "socketmsg">
    9. div>
    10. div>

  • 相关阅读:
    使用Rust编写爬虫代码来抓取精美的图片
    计算机网络:根据IP和子网掩码计算网络号
    关于qt中label挡住了dockwidget的窗体边缘
    pytest自动化测试两种执行环境切换的解决方案
    学习笔记——交通安全分析13
    一文读透react精髓
    SOC的多核启动流程详解
    在Ubuntu 系统下开发GUI,用哪种开发工具比较好?
    记录--移动端的双击事件好不好用?
    pkg-config使用
  • 原文地址:https://blog.csdn.net/qq3892997/article/details/134440924