• 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

  • 相关阅读:
    Linux命令行和Shell脚本编程
    Excel自动触发时间
    dom4j读取xml文件 简单例子
    GSM & Foxit Reader
    ThreadPoolExecutor 线程池
    Linux /var/log
    delphi开发技巧
    利用ScktSrvr打造多功能Socket服务器
    delphi中Windows消息大全使用详解
    自己构造注入点方便入侵
  • 原文地址:https://www.cnblogs.com/niceyoo/p/10913564.html
Copyright © 2020-2023  润新知