zoukankan      html  css  js  c++  java
  • WebSocket 实现前后端通信的笔记

    之前在做站内信时,用到了 WebSocket ,整理了一些笔记分享如下。
    本文基于 SpringBoot 2.1.5,本文不涉及环境搭建。

    引入依赖

    在 Spring 中要使用 WebSocket 功能,需要在pom中引入依赖:

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-websocket</artifactId>
    </dependency>

    配置类

    增加一个配置类,用于定义 WebSocket 全局配置信息

    @Configuration
    @EnableWebSocketMessageBroker
    public class WebSocketStompConfig implements WebSocketMessageBrokerConfigurer {

        /**
         * 注册stomp端点
         * @param registry
         */

        @Override
        public void registerStompEndpoints(StompEndpointRegistry registry) {

            ## 允许使用socketJs方式访问 即可通过http://IP:PORT/xboot/ws来和服务端websocket连接
            registry.addEndpoint("/tmax/ws").setAllowedOrigins("*").withSockJS();
        }

        /**
         * 配置信息代理
         * @param registry
         */

        @Override
        public void configureMessageBroker(MessageBrokerRegistry registry) {

            ## 订阅Broker名称 user点对点 topic广播即群发
            registry.enableSimpleBroker("/user","/topic");
            ## 全局(客户端)使用的消息前缀
            registry.setApplicationDestinationPrefixes("/app");
            ## 点对点使用的前缀 无需配置 默认/user
            registry.setUserDestinationPrefix("/user");
        }
    }

    来看一下这两个方法:

    1、registerStompEndpoints(StompEndpointRegistry registry)

    注册stomp端点。起到的作用就是添加一个服务端点,来接收客户端的连接,
    registry.addEndpoint("/tmax/ws") 表示添加了一个 /tmax/ws 端点,客户端可以通过这个端点来进行连接。withSockJS() 的作用是开启 SockJS 访问支持,即可通过http://IP:PORT/tmax/ws 来和服务端 websocket 连接。

    2、configureMessageBroker(MessageBrokerRegistry registry)

    配置信息代理。定义消息代理,设置消息连接请求的各种规范信息。
    registry.enableSimpleBroker("/user","/topic") 表示客户端订阅地址的前缀信息,也就是客户端接收服务端消息的地址的前缀信息(比较绕,看完整个例子,大概就能明白了)registry.setApplicationDestinationPrefixes("/app") 指服务端接收地址的前缀,意思就是说客户端给服务端发消息的地址的前缀。
    registry.setUserDestinationPrefix("/user") 指推送用户前缀。

    我不不难发现,setApplicationDestinationPrefixessetUserDestinationPrefix 起到的效果敲好相反,一个定义了客户端接收的地址前缀,一个定义了客户端发送地址的前缀。

    开始业务代码的编写

    先了解几个知识点,下方会用到。

    1、MessageMapping

    接收客户端请求连接注解。Spring 对于 WebSocket 封装的特别简单,提供了一个 @MessageMapping 注解,功能类似 @RequestMapping,它是存在于Controller中的,定义一个消息的基本请求,功能也跟 @RequestMapping类似,包括支持通配符 的url定义等等。

    2、SimpMessagingTemplate

    SimpMessagingTemplate 是 Spring-WebSocket 内置的一个消息发送工具,可以将消息发送到指定的客户端。

    3、SendTo

    @SendTo 可以把消息广播到路径上去,例如下面可以把消息广播到 "/topic/greetings”,如果客户端在这个路径订阅消息,则可以接收到消息

    接下来看一下后台代码实现,HelloController

    /**
     * @author niceyoo
     */

    @Slf4j
    @Controller
    @Api(description = "hello接口")
    @Transactional
    public class HelloController {

        @Autowired
        private SimpMessagingTemplate messagingTemplate;

        /**
         * 跳转至hello.html界面
         * @return
         */

        @RequestMapping("/hello")
        public String hello(){
            return "hello";
        }

        /**
         * 接收然后转发至客户端消息
         * @param message
         * @return
         * @throws Exception
         */

        @MessageMapping("/top")
        @SendTo("/topic/greetings")
        public String greeting(String message) throws Exception {
            System.out.println("receiving " + message);
            System.out.println("connecting successfully.");
            return "AAA:"+message;
        }

        /**
         * 推送消息
         * @return
         */

        @ResponseBody
        @RequestMapping("/hello/addMessage")
        public Result<Object> addMessage(){
            messagingTemplate.convertAndSend("/topic/greetings""您收到了新的系统消息");
            return new ResultUtil<Object>().setSuccessMsg("添加成功");
        }

    }

    hello.html 代码:

    <!doctype html>
    <html>
    <head>
        <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
        <script src="https://cdn.bootcss.com/sockjs-client/1.3.0/sockjs.js"></script>
        <script src="https://cdn.bootcss.com/stomp.js/2.3.3/stomp.js"></script>
        <style>
            .box {
                 300px;
                float: left;
                margin: 0 20px 0 20px;
            }
            .box div, .box input {
                border: 1px solid;
                -moz-border-radius: 4px;
                border-radius: 4px;
                 100%;
                padding: 0px;
                margin: 5px;
            }
            .box div {
                border-color: grey;
                height: 300px;
                overflow: auto;
            }
            .box input {
                height: 30px;
            }
            h1 {
                margin-left: 30px;
            }
            body {
                background-color: #F0F0F0;
                font-family: "Arial";
            }
        </style>
    </head>
    <body lang="en">
    <h1>Index</h1>
    <div id="first" class="box">
        <div></div>
        <input autocomplete="off" value="Type here..."></input>
        <button onclick="connect()">登陆客户端</button>
        <button onclick="send()">发送消息</button>
    </div>
    <script>
        var stompClient = null;
        var sockjs_url = '/tmax/ws';

        function connect() {
            var sockjs = new SockJS(sockjs_url);
            stompClient = Stomp.over(sockjs);
            stompClient.connect({}, function(frame) {
                console.log('Connected: ' + frame);
                stompClient.subscribe('/topic/greetings', function(greeting){
                    console.log("返回内容:"+greeting.body);
                    print('服务器:', greeting.body);
                });
            });
        }

        function send() {
            if(stompClient == null){
                print('系统提示:', '请先点击客户端登陆');
                return false;
            }
            print('客户端:', inp.val());
            stompClient.send("/app/top", {}, inp.val());
            inp.val('');
        }

        $('#first input').focus();
        var div  = $('#first div');
        var inp  = $('#first input');

        var print = function(m, p) {
            p = (p === undefined) ? '' : p;
            div.append($("<code>").text(m + ' ' + p));
            div.append($("<br>"));
            div.scrollTop(div.scrollTop()+10000);
        };

    </script>
    </body>
    </html>

    操作流程:

    点击“登录客户端”,输入框内输入内容,点击发送消息。

    消息推送

    关于消息的推送,借助 postman,调用 http://127.0.0.1:8888/hello/addMessage,实现后端推送至客户端。

    额外补充,关于消息推送,往往会用到推送至指定用户,则:messagingTemplate.convertAndSendToUser(id,"/queue/subscribe", "您收到了新的消息"); ,其中id为系统用户id。

    详细可搜索 SimpMessagingTemplate 的一些用法。

    如果文章有错的地方欢迎指正,大家互相留言交流。习惯在微信看技术文章,想要获取更多的Java资源的同学,可以关注微信公众号:niceyoo

    参考地址:https://www.jianshu.com/p/60799f1356c5

  • 相关阅读:
    codeforces C. Cows and Sequence 解题报告
    codeforces A. Point on Spiral 解题报告
    codeforces C. New Year Ratings Change 解题报告
    codeforces A. Fox and Box Accumulation 解题报告
    codeforces B. Multitasking 解题报告
    git命令使用
    shell简单使用
    知识束缚
    php 调用系统命令
    数据传输方式(前端与后台 ,后台与后台)
  • 原文地址:https://www.cnblogs.com/niceyoo/p/10913564.html
Copyright © 2011-2022 走看看