SpringBoot WebSocket前后端分离 登陆发布订阅一对多数据推送

服务器根据用户订阅推送对应数据
引入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>
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值