背景:在原有通知公告的基础上,把通知公共的推送服务修改为其他业务收到紧急订单发送公告到消息队列MQ,然后在js中创建一个socket去监听公告,收到公告后刷新所有在订单页面的用户的页面列表(重点就是用户在收到紧急订单时能及时刷新页面并播报语音),语音播报功能可参考我以前的博文,当前功能只是在原有功能的基础上添加接收到公告时刷新列表(刷新列表完成后就会自动播报语音,这是之前已经完成的功能)
maven依赖:
org.springframework.boot
spring-boot-starter-websocket
org.springframework.boot
spring-boot-starter-amqp
注意事项: 一个系统建议只调用一次 creatSocket()方法,否则创建多个 socket实例就最好是创建多个creatSocket()方法,否则多次创建实例都会接收到相同的广播没有意义
private AmqpTemplate amqpTemplate;
@PostMapping("/sendEkanbanYouXian") //不能在列表刷新的地方触发推送 ,需求页面刷新时发送广播会触发所有人都刷新页面,所有人刷新又会触发所有人再次发送广播,因此造成死循环
public String sendEkanbanYouXian(String msg) {
// 此处进行数据库操作 ----目前省略,待有需要再加进去
//WebSocketServer.sendInfo(form.getMessage());//只能推送给一台服务器的用户(193/4)
this.amqpTemplate.convertAndSend("fanout.exchange.msg","", msg); //使用队列给所有用户发送信息
return "广播推送成功【" + msg + "】";
}
$.post("/socket/sendEkanbanYouXian", {msg: jiajiText}, function(res) { //业务js中把需要广播的消息发送到消息队列
layer.msg(res);
});
var socket;
function creatSocket(){
if (typeof (WebSocket) == "undefined") {
console.log("您的浏览器不支持WebSocket");
} else {
console.log("您的浏览器支持WebSocket");
//实现化WebSocket对象,指定要连接的服务器地址与端口 建立连接
//等同于socket = new WebSocket("ws://localhost:8083/checkcentersys/websocket/20");
var curWwwPath = window.document.location.href;// 当前网址
// 获取主机地址
var pathName = window.document.location.pathname;
var pos = curWwwPath.indexOf(pathName);
var localhostPath = curWwwPath.substring(0, pos);
var socketPath = localhostPath.replace('http','ws');
//用ajax同步取IP
var serverIP="";
var clientIP="";
var postData = {};
$.ajax({
type : "get",
url : "/socket/getServerIp",
data : postData,
async: false,
cache : false,
success : function(data) {
if (data != null) {serverIP = data; }else{alert("取不到ServerIP");}
},
error : function(data) { alert("取ServerIP异常!");}
});
$.ajax({
type : "get",
url : "/socket/getClientIp",
data : postData,
async: false,
cache : false,
success : function(data) {
if (data != null) {clientIP = data;} else{alert("取不到ClientIP");}
},
error : function(data) {alert("取ClientIP异常!");}
});
socketPath = "ws://"+serverIP+":8101"; //socketPath = "ws://172.16.183.127:8101";
var loginUserId = document.getElementById("loginUserId").value;
socket = new WebSocket(socketPath + "/websocket/" + clientIP + "/" + loginUserId);
//打开事件
socket.onopen = function() {console.log("Socket 已打开");};
socket.onmessage = function(msg) {//获得消息事件 (监听广播)
$("#mteSearchBtn").click();//收到广播触发页面列表的刷新
if (msg.data != "连接成功" && msg.data !="") {//发现消息进入 开始处理前端触发逻辑
layer.open({
type: 1,
offset: 'rt',
anim: 'slideDown', // 从上往下(右上角)
area: ['30%', '160px'],
skin: 'layui-layer-molv',
shade: 0.1,
shadeClose: true,
id: 'ID-demo-layer-direction-t',
content: ''+msg.data+''
});
}
};
//关闭事件
socket.onclose = function() {console.log("Socket已关闭");};
//发生了错误事件
socket.onerror = function() {alert("Socket发生了错误");}//此时可以尝试刷新页面
}
}
重点:主要就是监听到广播后,调用页面的搜索按钮,进行从新加载列表
4.1 替换上面的JS接收socket的部分(重点就是弹出层的动画效果):
socket.onmessage = function(msg) {//获得消息事件 (监听广播)
if (msg.data != "连接成功" && msg.data !="") {//发现消息进入 开始处理前端触发逻辑
$("#socket").fadeIn(3000);
$("#socketmsg").html(msg.data);
$("#mteSearchBtn").click();//收到消息就立马让页面触发刷新 (物料需求页面列表刷新,页面刷新自然就有语音,因此这个功能因为这句代码导致暂时只能适用于 物料需求页面),$("#mteSearchBtn")必须是这样触发,不能直接写mteSearchBtn.click否则无效
// 开启定时器
function startTimes() {
var i = 10;
var timer = window.setInterval(function() {
console.log('还有' + (--i) + '秒关闭socket广播窗口!');
if (i <= 0) {
window.clearInterval(timer);
console.log('已关闭socket广播窗口!');
$("#socket").fadeOut(3000);
$("#socket").fadeTo("3000", 0.7);
}
}, 1000);
}
startTimes();
}
getOnlineCountJS(); //获取在线人数
};
4.2 html
消息通知