美文网首页
Springboot 技术整合--笔记6--集成websocke

Springboot 技术整合--笔记6--集成websocke

作者: 牵手生活 | 来源:发表于2019-05-29 11:28 被阅读0次

    WebSocket的ping与pong的java实现…

    理解几个知识点

    • 订阅地址 :如stompEndpointRegistry.addEndpoint("/endpointWechat") 或使用@ServerEndpoint创建
    • 容许跨域
    • 是否开启SockJS支持
    • 推送:声明SimpMessagingTemplate ,调用convertAndSend方法(或者使用@SendTo和@SendToUser注解)
    • 一对一发送消息
    • Principal:身份验证和授权
    • stomp协议:STOMP即Simple (or Streaming) Text Orientated Messaging Protocol,简单(流)文本定向消息协议,它提供了一个可互操作的连接格式,允许STOMP客户端与任意STOMP消息代理(Broker)进行交互。
    • WebSocket(stomp服务端)
    websocket.jpg

    WebSocketSession 发送的消息类型(sendMessage)

    前端涉及js

    • jquery
    • sockJs :
    • stomp.min.js(stomp客户端)
    • STOMP Simple (or Streaming) Text Orientated Messaging Protocol,简单(流)文本定向消息协议,它提供了一个可互操作的连接格式,允许STOMP客户端与任意STOMP消息代理(Broker)进行交互

    js 前端链接websocket的方式

    STOMP 链接成功、失败、主动断开等参阅
    STOMP 客户端 API 整理:https://blog.csdn.net/jqsad/article/details/77745379

    html页面,连接stomp服务端,订阅/topic/myTop的消息(订阅topic或myTop)

    
    方式1:
    var socket = new SockJS('/endpointWechat'); 
    方式2
        //前台 js 中 new SockJS 的时候,一起是3个参数项的,另外2个参数项可以传递目前是哪个用户的标识,这样就可以在后台区分出来连接是哪个用户建立的
        var socket = new SockJS(url, undefined, {protocols_whitelist: ['websocket']});
    
    方式3:直接携带参数
    var socket = new SockJS('/endpointWechat'+ '?token='+str_token); //'?token=token8888'
    
    

    Android端的链接方式

    SpringBoot 使用的websocket 协议,不是标准的websocket协议,使用的是名称叫做STOMP的协议。
    要想与js方式调用:stompClient.send("/sendServer", {}, JSON.stringify({ 'name': message }));,需要Android采用STOMP方式调用

    更多细节参考
    stomp协议 官方:http://stomp.github.io/
    csdn 大神博客:http://blog.csdn.net/chszs/article/details/5200554
    iteye 大神博客 http://diaocow.iteye.com/blog/1725186 (务必看一下,了解协议的一些使用)
    SpringBoot webSocket 发送广播、点对点消息,Android接收

    WebSocket可以应用于即时通信等场景,比如现在直播很火热,直播中的弹幕也可以使用WebSocket去实现。
    WebSocket的协议内容可以见 The WebSocket Protocol,讲得最全面的官方说明。简单介绍可以见维基百科WebSocket
    在Android客户端,一般可以使用下面的库完成WebSocket通信

    • okhttp,一般人我不告诉他okhttp还可以用来进行WebSocket通信
    • Java-WebSocket,纯java实现的WebSocket客户端和服务端实现
    image.png

    Android最佳实践——深入浅出WebSocket协议:https://blog.csdn.net/blueangle17/article/details/80701152


    springboot 的工程


    image.png

    pom.xml引入

            <!--添加websocket依赖-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-websocket</artifactId>
            </dependency>
    
            <!--添加alibaba 的fastjson引用-->
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>fastjson</artifactId>
                <version>1.2.46</version>
            </dependency>
    
    

    编写MyHandShakeInterceptor类(主要作用用于对握手前检查合法性)

    // 初始化对象,拦截握手,发生在链接之前
    @Component
    public class MyHandShakeInterceptor implements HandshakeInterceptor {
    
        private static final Logger log = LoggerFactory.getLogger(MyHandShakeInterceptor.class);
        @Override
        public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception {
    
    
            //http://localhost:8080/endpointWechat/948/dtdzvrrs/websocket?token=token8888
            //js调用:
            //        var host="http://localhost:8080";
            //        var socket = new SockJS(host+'/endpointWechat' + '?token=token8888');
    
            log.info("this.getClass().getCanonicalName() = {},在这里决定是否允许链接,http协议转换websoket协议进行前, 握手前Url = {}",this.getClass().getCanonicalName(),request.getURI());
    
    
            //System.out.println(this.getClass().getCanonicalName() + " 在这里决定是否允许链接,http协议转换websoket协议进行前, 握手前"+request.getURI() );
    
    
            // http协议转换websoket协议进行前,可以在这里通过session信息判断用户登录是否合法
            //request.getURI().getPath(); //   /endpointWechat/896/mdoqjqia/websocket
            //request.getURI().getHost();//localhost
            //request.getURI().string  ; //  http://localhost:8080/endpointWechat/896/mdoqjqia/websocket?token=token8888
            //request.getURI().getQuery() ;  // token=token8888
            if (request instanceof ServletServerHttpRequest) {
                ServletServerHttpRequest servletServerHttpRequest = (ServletServerHttpRequest) request;
                HttpServletRequest httpRequest = servletServerHttpRequest.getServletRequest();
    
                String myToken = httpRequest.getParameter("token");
                if (null != myToken && !StringUtils.isEmpty(myToken)){
                    WebSocketSession webSocketSession = SocketManager.get(myToken);
                    if (webSocketSession != null){
                        log.info("token = {},已经在建立链接列表,不允许重复链接",myToken);
    
                    }else {
                        return true;
    
                    }
                }
    
    
    
            }
    
            return false;  //不允许建立链接
    
            //return true;
        }
    
        @Override
        public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Exception ex) {
            //握手成功后,
            System.out.println(this.getClass().getCanonicalName() + "握手成功后...");
        }
    }
    
    
    不允许创建连接的情况

    成功连接的情况


    成功连接的情况

    配置类WebSocketConfig

    @Configuration
    @EnableWebSocketMessageBroker
    public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
        @Autowired
        private MyHandShakeInterceptor myHandShakeInterceptor;
        @Override
        public void registerStompEndpoints(StompEndpointRegistry stompEndpointRegistry) {
            //以 /endpointWechat端点,客户端就可以通过这个端点来进行连接
            stompEndpointRegistry.addEndpoint("/endpointWechat").setAllowedOrigins("*")
                    .withSockJS();//开启SockJS支持
        }
    
        @Override
        public void configureMessageBroker(MessageBrokerRegistry registry) {
            registry.enableSimpleBroker("/topic","/user"); //客户端订阅服务的前缀
            registry.setUserDestinationPrefix("/user");  //开启一对一发送消息
        }
    
    }
    
    

    控制器WebScoketController

    
    /**
     * 创建人:牵手生活
     * 创建时间:2019-01-14 17:17
     */
    
    @Controller
    
    public class WebSocketController {
        @Autowired
        private SimpMessagingTemplate simpMessagingTemplate;  //声明SimpMessagingTemplate (或者使用@SendTo和@SendToUser注解),SimpMessagingTemplate可以在需要用到推送的地方如Controller,service,Component等地方
    
        private static final Logger log = LoggerFactory.getLogger(WebSocketController.class);
    
    
    
        // 收到消息记数
        private AtomicInteger count = new AtomicInteger(0);
    
    
    
    
        /**
         * @MessageMapping 指定要接收消息的地址,类似@RequestMapping。除了注解到方法上,也可以注解到类上
         * @MessageMapping("/receive") 对应html中的  stompClient.send("/app/receive", {}, JSON.stringify({ 'name': name }));
         * 多出来的“/app"是WebSocKetConfig中定义的,如不定义,则HTML中对应改为stompClient.send("/receive")
         * @SendTo默认 消息将被发送到与传入消息相同的目的地
         * 消息的返回值是通过{@link org.springframework.messaging.converter.MessageConverter}进行转换
         * @SendTo("/topic/getResponse") 指定订阅路径,对应HTML中的stompClient.subscribe('/topic/getResponse', ……)
         * 意味将信息推送给所有订阅了"/topic/getResponse"的用户
         * @param requestMessage
         * @return
         */
        @MessageMapping("/receive")
        @SendTo("/topic/getResponse")  //topic是广播全局通讯
        public ResponseMessage receive(RequestMessage requestMessage){
            log.info("receive message = {}" , JSONObject.toJSONString(requestMessage));
            ResponseMessage responseMessage = new ResponseMessage();
            responseMessage.setResponseMessage("响应消息WebSocketController receive [" + count.incrementAndGet() + "] records:"+JSONObject.toJSONString(requestMessage));
            return responseMessage;
        }
    
    
    
        /**
         * 客户端发消息,服务端接收
         *
         * @param requestMessage
         */
        // 相当于RequestMapping
        @MessageMapping("/sendServer")
        public void sendServer(RequestMessage requestMessage) {
            log.info("sendServer 客服端发送的,不需要发回给客户端message:{}", JSONObject.toJSONString(requestMessage));
        }
    
        @MessageMapping("/sendServer_str")
        public void sendServer_str(String message) {
            log.info("sendServer 客服端发送的,不需要发回给客户端message:{}", message);
        }
    
    
    
        /**
         * 客户端发消息,大家都接收,相当于直播说话
         *
         * @param message
         * @return
         */
        @MessageMapping("/sendAllUser_str")
        @SendTo("/topic/sendTopic_str")
        public String sendAllUser_str(String message) {
            // 也可以采用template方式
            return "服务的处理后的:"+message;
        }
    
        @MessageMapping("/sendAllUser")
        @SendTo("/topic/sendTopic")
        public ResponseMessage sendAllUser(RequestMessage requestMessage) {
            log.info("sendTopic 请求message = {}" , JSONObject.toJSONString(requestMessage));
            ResponseMessage responseMessage = new ResponseMessage();
            responseMessage.setResponseMessage(JSONObject.toJSONString(requestMessage));
            return responseMessage;
        }
    
    
    
        /**
         * 点对点用户聊天,这边需要注意,由于前端传过来json数据,所以使用@RequestBody
         * 这边需要前端开通var socket = new SockJS(host+'/myUrl' + '?token=token8888');   token为指定name
         * @param map
         */
        @MessageMapping("/sendMyUser")
        public void sendMyUser(@RequestBody Map<String, String> map) {
            log.info("sendMyUser 请求 map = {}", map);
            WebSocketSession webSocketSession = SocketManager.get(map.get("name"));
            if (webSocketSession != null) {
                log.info("sendMyUser sessionId = {}", webSocketSession.getId());
    
                //生成IJSONResult对象的data数据
                ResponseMessage responseMessage = new ResponseMessage();
                responseMessage.setResponseMessage("响应消息WebSocketController sendMyUser  records:"+map.get("message"));
                simpMessagingTemplate.convertAndSendToUser(map.get("name"), "/queue/sendUser", IJSONResult.ok(responseMessage));
    
                //simpMessagingTemplate.convertAndSendToUser(map.get("name"), "/queue/sendUser", JSONObject.toJSONString(responseMessage));  //ok
            }
        }
    
        @MessageMapping("/sendMyUser_obj")
        //@SendToUser("/user/queue/sendUser_obj")  //添加看看
        public ResponseMessage sendMyUser_obj(RequestMessage requestMessage) {
            log.info("sendMyUser message = {}" , JSONObject.toJSONString(requestMessage));
            ResponseMessage responseMessage = new ResponseMessage();
            responseMessage.setResponseMessage("响应消息WebSocketController sendMyUser [" + count.incrementAndGet() + "] records:"+JSONObject.toJSONString(requestMessage));
    
            return responseMessage;
        }
    
    
    
        //http://localhost:8080//wechatTask/websocket/index 转发到页面
        @RequestMapping(value="/wechatTask/websocket/index")
        public String websocketIndex(HttpServletRequest req){
    
            log.info("websocketIndex接口的 req.getRemoteHost(){}" , req.getRemoteHost());
            return "websocket/simple/websocket-index";
        }
    }
    
    
    

    添加thymeleaf的模板-websocket-index.html

    说明
    客户端可以通过使用Stomp.js和sockjs-client连接

    var socket = new SockJS('/endpointWechat'+ '?token='+str_token);  
    


    socket连接对象也可通过WebSocket(不通过SockJS)连接

    var socket=new WebSocket('/endpointWechat'+ '?token='+str_token);
    

    stompClient.connect()方法签名:

    client.connect(headers, connectCallback, errorCallback);
    

    websocket-index.html如下

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Spring Boot+WebSocket例子</title>
        <script src="https://cdn.bootcss.com/sockjs-client/1.3.0/sockjs.min.js"></script>
        <script src="https://cdn.bootcss.com/stomp.js/2.3.3/stomp.min.js"></script>
        <link href="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
        <script src="https://cdn.bootcss.com/vue/2.6.10/vue.min.js"></script>
        <!--引入jqurey库-->
        <script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
    <body  onload="disconnect()" >
    
    <div>
        <p> 创建链接:var socket = new SockJS(host+'/myUrl' + '?token=token8888')</p>
        <p>     token 是你上面输入的token 或username</p>
    
    
        <p>点击链接,如果链接成功,则可以与后台通过websocket进行通信 </p>
        <p>输入你要发送的内容(这里是你的名字--以后改为json对象)</p>
        <p>点击发送,会把输入的内容通过websocket发送到后台</p>
    
        <p>查看log 更多细节查看chrome的开发者选项中的控制台</p>
    
    </div>
    
    
    <div >
        <label >输入你新建链接是的token或name(用于点对点通信)?</label>
        <input type="text" id="mytoken"  value="wxid_on8oksh88zo22" placeholder="Your token/name here...如:4567"></input>
    </div>
    <div >
        <label id = "state-info" >***连接状态-未连接***</label>
    
    </div>
    </div>
    
    <div>
        <div>
            <button id="connect" onclick="connect();">连接</button>
            <button id="disconnect" disabled="disabled" onclick="disconnect();">断开连接</button>
        </div>
        <div id="conversationDiv">
            <label>输入你要发送的内容</label><input type="text" id="message"  value="fdsfs"/>
            <button id="sendName" onclick="sendName();">发送</button>
            <button id="sendServer" onclick="sendServer();">发送sendServer</button>
            <button id="sendTopic" onclick="sendTopic();">发送sendTopic</button>
            <button id="sendMyUser" onclick="sendMyUser();">发送点对点</button>
            <!--用于显示通过websocket的响应数据-->
            <p id="response"></p>
        </div>
    </div>
    
    
    <script type="text/javascript">
        var stompClient = null;
    
        function setConnected(connected) {
            document.getElementById('connect').disabled = connected;
            document.getElementById('disconnect').disabled = !connected;
            document.getElementById('conversationDiv').style.visibility = connected ? 'visible' : 'hidden';
            $('#response').html();
        }
    
        function connect() {
            //判断是否输入token
            var val = $('#mytoken').val();
            var str_token = val.replace(/(^\s*)|(\s*$)/g, '');//去除空格;
            if (str_token == '' || str_token == undefined || str_token == null){
                alert('建立链接前,需要输入token');
                return
            }
    
    
            // websocket的连接地址,此值等于WebSocketMessageBrokerConfigurer中registry.addEndpoint("/endpointWechat").withSockJS()配置的地址
            //var socket = new SockJS('/endpointWechat'); //
            //建立连接对象(还未发起连接)
            var socket = new SockJS('/endpointWechat'+ '?token='+str_token); //'?token=token8888'
            //利用Stomp协议创建socket客户端
            stompClient = Stomp.over(socket);
    
            /**
             * 调用stompClient中的connect方法来连接服务端,
             * 连接成功之后调用setConnected方法,该隐藏的隐藏,该显示的显示
             */
            stompClient.connect({},
                function(frame) {
                setConnected(true);
                console.log('连接成功Connected: ' + frame);
                document.getElementById("state-info").innerHTML = "***连接成功***";
                // 客户端订阅消息的目的地址:此值WebSocketController中被@SendTo("/topic/getResponse")注解的里配置的值
                stompClient.subscribe('/topic/getResponse', function(respnose){ //2
                    showResponse(JSON.parse(respnose.body).responseMessage);
                });
    
                //订阅queue===接收广播的
                stompClient.subscribe('/topic/sendTopic', function(response) {
                    showResponse(JSON.parse(response.body).responseMessage);
                    //showResponse((respnose.body).responseMessage);//string返回的处理
                });
    
                //接收发个单个人的===点对点===????????为什么会收不到
                var mytoken = $('#mytoken').val();
                stompClient.subscribe('/user/queue/sendUser', function(response) {  //  '/user/queue/sendUser'===/'+mytoken+'
                    //showResponse(JSON.parse(response.body).responseMessage);
                    showResponseBody(response.body);//直接显示response.body
    
                });
    
    
            },
                function errorCallBack (error) {
                    // 连接失败时(服务器响应 ERROR 帧)的回调方法
                    document.getElementById("state-info").innerHTML = "***连接失败***";
                    console.log('连接失败【' + error + '】');
                }
    
    
            );//end for connected
    
    
        }
    
    
        function disconnect() {
            if (stompClient != null) {
                stompClient.disconnect();
            }
            setConnected(false);
            document.getElementById("state-info").innerHTML = "***连接未连接***";
            console.log("Disconnected");
        }
    
    
        //后台采用@SendTo("/topic/getResponse")注解
        function sendName() {
            var message = $('#message').val();
            // 客户端消息发送的目的:服务端使用WebSocketController中@MessageMapping("/receive")注解的方法来处理发送过来的消息
            stompClient.send("/receive", {}, JSON.stringify({ 'name': message }));
        }
    
    
        //后台采用@SendTo("/topic/getResponse")注解
        function sendName() {
            var message = $('#message').val();
            // 客户端消息发送的目的:服务端使用WebSocketController中@MessageMapping("/receive")注解的方法来处理发送过来的消息
            stompClient.send("/receive", {}, JSON.stringify({ 'name': message }));
        }
    
        function sendTopic() {  //发公告===类似发群公告
            var message = $('#message').val();
            // 客户端消息发送的目的:服务端使用WebSocketController中@MessageMapping("/receive")注解的方法来处理发送过来的消息
            stompClient.send("/sendAllUser", {}, JSON.stringify({ 'name': message }));
        }
    
        function sendServer() {  //发送到服务端,server不返回数据
            var message = $('#message').val();
            // 客户端消息发送的目的:服务端使用WebSocketController中@MessageMapping("/receive")注解的方法来处理发送过来的消息
            stompClient.send("/sendServer", {}, JSON.stringify({ 'name': message }));
        }
    
        function sendAllUser() {  //发公告===类直接发到群中,其实跟公告一样
            var message = $('#message').val();
            // 客户端消息发送的目的:服务端使用WebSocketController中@MessageMapping("/receive")注解的方法来处理发送过来的消息
            stompClient.send("/sendAllUser", {}, JSON.stringify({ 'name': message }));
        }
    
        //发送点对点通信---后台对应的采用的是simpMessagingTemplate.convertAndSendToUser
        function sendMyUser() {
            var message = $('#message').val();
            var mytoken = $('#mytoken').val();
            // 客户端消息发送的目的:服务端使用WebSocketController中@MessageMapping("/receive")注解的方法来处理发送过来的消息
            //stompClient.send("/sendMyUser", {}, JSON.stringify({ 'name': message }));
    
            stompClient.send("/sendMyUser", {}, JSON.stringify({name:mytoken,message:message}));
    
        }
    
        //显示消息
        function showResponse(message) {
            var response = $("#response");
            response.html("按ResponseMessage对象返回的responseMessage字段数据:\""+message + "<br\>" + response.html());
        }
    
        function showResponseBody(response_body) {
            var response = $("#response");
            response.html("按websocket api 返回格式的response.body数据:"+response_body + "<br\>" + response.html());
        }
    
    </script>
    </body>
    </html>
    

    通过controller转发到html访问websocket

    
    http://localhost:8080//wechatTask/websocket/index
    
    
    websocket链接情况

    添加Socket链接的管理器SocketManager

    image.png
    public class SocketManager {
        private static final Logger log = LoggerFactory.getLogger(SocketManager.class);
        private static ConcurrentHashMap<String, WebSocketSession> manager = new ConcurrentHashMap<String, WebSocketSession>();
    
        public static void add(String key, WebSocketSession webSocketSession) {
            log.info("新添加webSocket连接 {} ", key);
            manager.put(key, webSocketSession);
        }
    
        public static void remove(String key) {
            log.info("移除webSocket连接 {} ", key);
            manager.remove(key);
        }
    
        public static WebSocketSession get(String key) {
            log.info("获取webSocket连接 {}", key);
            return manager.get(key);
        }
    
        public static int connectedCount(){
            return manager.size();
        }
    
    
    }
    
    

    添加WebSocketDecoratorFactory(用于管理websocket的链接与断开)

    
    /**
     * 服务端和客户端在进行握手时会被执行
     */
    @Component
    public class WebSocketDecoratorFactory implements WebSocketHandlerDecoratorFactory {
        private static final Logger log = LoggerFactory.getLogger(WebSocketDecoratorFactory.class);
        @Override
        public WebSocketHandler decorate(WebSocketHandler handler) {
            return new WebSocketHandlerDecorator(handler) {
                @Override
                public void afterConnectionEstablished(WebSocketSession session) throws Exception {
                    log.info("有人连接啦  sessionId = {}", session.getId()+"链接数量"+SocketManager.connectedCount()+"****连接数一直为0则是校验了taken");
    
                    Principal principal = session.getPrincipal();
                    if (principal != null) {
                        log.info("key = {} 存入", principal.getName());
                        // 身份校验成功,缓存socket连接
                        SocketManager.add(principal.getName(), session);
                    }
    
    
                    super.afterConnectionEstablished(session);
                }
    
                @Override
                public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception {
                    log.info("有人退出连接啦  sessionId = {}", session.getId()+SocketManager.connectedCount());
                    Principal principal = session.getPrincipal();
                    if (principal != null) {
                        // 身份校验成功,移除socket连接
                        SocketManager.remove(principal.getName());
                    }
                    super.afterConnectionClosed(session, closeStatus);
                }
            };
        }
    }
    

    WebSocketConfig中注入WebSocketDecoratorFactory,并重写configureWebSocketTransport方法


    image.png java spring 后台日志 2个浏览器连接后收到不同的信息

    关于websocket的文章收录

    JMeter测试WebSocket的经验总结
    springboot集成websocket需要的都在这里

    image.png 效果图

    Spring Boot系列十六 WebSocket简介和spring boot集成简单消息代理

    image.png

    使用spring boot +WebSocket实现(后台主动)消息推送-@ServerEndpoint创立websocket endpoint--实现onOpen、onError、onClose

    //socket = new WebSocket("ws://localhost:9094/starManager/websocket/张三");
            var socket;
            if(typeof(WebSocket) == "undefined") {
                console.log("您的浏览器不支持WebSocket");
            }else{
                console.log("您的浏览器支持WebSocket");
                
                //实现化WebSocket对象,指定要连接的服务器地址与端口  建立连接
                //socket = new WebSocket("ws://localhost:9094/starManager/websocket/张三")
    
                socket = new WebSocket("ws://localhost:9094/starManager/websocket");
                //打开事件
                socket.onopen = function() {
                    console.log("Socket 已打开");
                    //socket.send("这是来自客户端的消息" + location.href + new Date());
                };
                //获得消息事件
                socket.onmessage = function(msg) {
                    console.log(msg.data);
                    //发现消息进入    调后台获取
                    getCallingList();
                };
                //关闭事件
                socket.onclose = function() {
                    console.log("Socket已关闭");
                };
                //发生了错误事件
                socket.onerror = function() {
                    alert("Socket发生了错误");
                }
                 $(window).unload(function(){
                      socket.close();
                    });
     
    //                                  $("#btnSend").click(function() {
    //                                      socket.send("这是来自客户端的消息" + location.href + new Date());
    //                                  });
    //
    //                                  $("#btnClose").click(function() {
    //                                      socket.close();
    //                                  });
            }
    
    

    SpringBoot使用WebSocket--SimpMessagingTemplate
    声明SimpMessagingTemplate (或者使用@SendTo和@SendToUser注解)
    在需要用到推送的地方如Controller,service,Component等地方声明SimpMessagingTemplate
    当需要向客户端推送消息时,调用convertAndSend方法,即可推送消息,此处“/topic/send”可随意设置,所有前端订阅该url的客户端都可以收到推送的消息。

    messagingTemplate.convertAndSend("/topic/send", result);
    

    springboot+websocket,一篇足够了--管理Socket的类-SocketManager
    springboot+websocket,一篇足够了--管理Socket的类-SocketManager -简书
    Spring-boot2 WebFlux WebSockit实现-实现心跳
    websocket消息推送实现
    [java+websocket实现网页聊天室-今日头条](https://www.toutiao.com/a6700358112806699528
    spring websocket之sockjs超简单现实
    客户端接收服务端消息推送sockjs-client的使用--new SockJS(url, _reserved, options)
    利用Spring_Boot WebSocKet实现一个推送的小Demo--全局推送&点对点推动-spring-boot-starter-security
    Spring Boot通信之STOMP协议:后台不发送心跳的问题

    image.png

    spring boot集成WebSocket实时输出日志到web页面--采用阻塞队列
    Spring消息之STOMP--留意参数Principal principal
    什么是stomp?spring-boot websocket stomp服务构建-@MessageMapping参数详情

    相关文章

      网友评论

          本文标题:Springboot 技术整合--笔记6--集成websocke

          本文链接:https://www.haomeiwen.com/subject/fruetctx.html