服务器根据用户订阅推送对应数据
引入WebSocket
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
import cn.meiot.config.WebSocketConfig;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;
@ServerEndpoint(value = "/verify/wss", configurator = WebSocketConfig.class)
@Component
@Slf4j
public class WebSocketServer {
private Session session;
public static CopyOnWriteArraySet<WebSocketServer> webSocketSet = new CopyOnWriteArraySet<WebSocketServer>();
public static ConcurrentHashMap<String, Set<WebSocketServer>> subscribeSerial = new ConcurrentHashMap<String, Set<WebSocketServer>>();
/**
* 连接建立成功调用的方法
*/
@OnOpen
public void onOpen( Session session) {
//设置最大空闲时间
//60S内必须登陆否则断连
session.setMaxIdleTimeout(60000);
this.session = session;
}
/**
* 连接关闭调用的方法
*/
@OnClose
public void onClose(Session session) {
webSocketSet.remove(this);
}
/**
* 收到客户端消息后调用的方法
*例如传入{ "cmd":"1","token":"asdsafsa"} 做登陆
*例如传入{"cmd":2,"topic":"OEJDOTM2MDlFNjc5OUM4NzhCNDE3NEU4OEI2RTMwQzc="} 订阅某一个主题
*例如传入{"cmd":3,"topic":"OEJDOTM2MDlFNjc5OUM4NzhCNDE3NEU4OEI2RTMwQzc="} 退订某一个主题
*例如传入{"cmd":4} 心跳续命
*这些规则根据自己需要修改
* @param message 客户端发送过来的消息
*/
@OnMessage
public void onMessage(String message,Session session) throws IOException {
JSONObject jsonObject = JSONObject.parseObject(message);
String cmd = jsonObject.getString("cmd");
if("1".equals(cmd)){
//此处做登陆规则
//如果登陆成功加进去
webSocketSet.add(this);
session.getBasicRemote().sendText("登录成功");
}
boolean cmd2 = "2".equals(cmd);
boolean cmd3 = "3".equals(cmd);
if( cmd2 || cmd3){
if(webSocketSet.contains(this)){
String topic = jsonObject.getString("topic");
if(cmd2){
addSubscribeSerial(group,session);
}else{
removeSubscribeSerial(group,session);
}
}
return;
}else if("4".equals(cmd)){
//判断是否登陆的数组里面存在当前用户
if(webSocketSet.contains(this)){
return;
}
}
webSocketSet.remove(session);
session.getBasicRemote().sendText("请登录!!!");
session.close();
}
public static void sendMessage(String group,String message) {
//推送时加锁
synchronized ("sub"+group) {
Set<WebSocketServer> webSocketServers = WebSocketServer.subscribeSerial.get(group);
if (org.springframework.util.CollectionUtils.isEmpty(webSocketServers)) {
return;
}
Iterator<WebSocketServer> iterator = webSocketServers.iterator();
while (iterator.hasNext()) {
Session next = iterator.next().session;
try{
if (next == null || !next.isOpen()) {
iterator.remove();
next.close();
continue;
}
next.getBasicRemote().sendText(message);
//next.getBasicRemote().flushBatch();
}catch (Exception e){
e.getStackTrace();
log.error("websocket推送数据异常:"+e.getMessage());
}
log.info("当前订阅分组:{},当前订阅sessionId:{}",group,next.getId());
}
}
}
public void addSubscribeSerial(String serialNumber,Session session){
synchronized ("sub"+serialNumber){
Set<WebSocketServer> webSocketServers = subscribeSerial.get(serialNumber);
if(webSocketServers == null){
webSocketServers = new HashSet<>();
}
webSocketServers.add(this);
subscribeSerial.put(serialNumber,webSocketServers);
}
}
public void removeSubscribeSerial(String serialNumber,Session session){
synchronized ("sub"+serialNumber){
Set<WebSocketServer> webSocketServers = subscribeSerial.get(serialNumber);
if(CollectionUtils.isEmpty(webSocketServers)){
return;
}
webSocketServers.remove(this);
subscribeSerial.put(serialNumber,webSocketServers);
}
}
测试网页
<!DOCTYPE html>
<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title></title>
<style type="text/css">
.new {
background: green;
}
</style><style type="text/css" abt="234"></style></head>
<body style="">
websocket调试页面()
<div>
<textarea id="msg1" name="msg" cols="80" rows="3"> {"cmd": "1", "token":"NDRBQTdBNjFERDlEOEMxMEI4QjREQzNEQkNDMzI0MDQ="}
</textarea>
<button id="button1" onclick="sendMsg(1)" name="">登录</button>
</div>
<div>
<textarea id="msg2" name="msg" cols="80" rows="6"> {"cmd": "2", "topic":"M2202009140001"}
</textarea>
<button id="button2" onclick="sendMsg(2)" name="">订阅</button>
</div>
<div>
<textarea id="msg3" name="msg" cols="80" rows="6"> {"cmd": "3", "topic":"M2202009140001"}
</textarea>
<button id="button3" onclick="sendMsg(3)" name="">取消订阅</button>
</div>
<div>
<input type="text" id="token" style="width:400px;" name="checktoken" value="QzRBOTI4NkMxNDc1RTg2MTU2MjA2RUYyMjU1RTM0ODk=">
<button id="button4" onclick="checktoken()" name="">token验证</button>
</div>
<div id="content">
<ul id="message-list">
</ul>
</div>
<script type="text/javascript" src="./websocket_files/jquery-3.4.1.min.js.下载"></script>
<script type="text/javascript">
var ws = new WebSocket("ws://127.0.0.1/verify/wss");
ws.onopen = function(evt) {
console.log("Connection open ...");
var ping = '{"cmd": 1,"token":"RDdERDlDNkYwRDc1QjhCRkQ3MDUzODhFMzQ2QjQwMjE="}';
ws.send(ping);;
setInterval(function(){
var ping = '{"cmd": 4}';
console.log(ping);
ws.send(ping);;
}, 30000);
};
function sendMsg(number)
{
var msg = $('#msg'+number).val();
ws.send(msg);
}
ws.onmessage = function(evt) {
//alert(evt);
var data = evt.data;
console.log(evt);
var now = new Date();
var hour = now.getHours();//得到小时
var minu = now.getMinutes();//得到分钟
var sec = now.getSeconds();//得到秒
var time = hour+':'+minu+':'+sec;
$('li').removeClass('new');
str = '<li class="new"><h5>'+time+'###'+data+'</h5></br><span>'+data+'</span></br></li>';
str += $('#message-list').html();
$('#message-list').html(str);
// ws.close();
};
/* ws.onclose = function(evt) {
//alert("WebSocket断开");
//window.location.reload();
console.log("Connection closed.");
};*/
</script>
</body></html>