• Springboot websocket使用


    1)基本概念

    1.http与websocket
    http超文本传输协议,大家都非常熟悉,http有1.0、1.1、 2.0几个版本,从http1.1起,默认都开启了Keep-Alive,保持连接持续性。
    简单地说,当一个网页打开完成后,客户端和服务器之间用于传输http数据的TCP连接不会关闭,如果客户端再次访问这个服务器上的网页,会继续使用这一条已经建立的连接,这样就降低了资源的消耗优化性能,但是Keep-Alive也是有时间限制的。
    还有一个客户端只能主动发起请求才能获取返回数据,并不能主动接收后台推送的数据,websocket便应运而生。

    websocket 是 html5新增加特性之一,目的是浏览器与服务端建立全双工的通信方式,解决 http 请求-响应带来过多的资源消耗,同时对特殊场景应用提供了全新的实现方式,比如聊天、股票交易、游戏等对对实时性要求较高的行业领域。

    http与websocket都是基于TCP(传输控制协议)的,websocket可以看做是对http协议的一个补充

    2.SockJs
    SockJS是一个JavaScript库,为了应对许多浏览器不支持WebSocket协议的问题,设计了备选SockJs。
    SockJS 是 WebSocket 技术的一种模拟。SockJS会尽可能对应 WebSocket API,但如果WebSocket 技术不可用的话,会自动降为轮询的方式。

    3.Stompjs
    STOMP—— Simple Text Oriented Message Protocol——面向消息的简单文本协议。
    SockJS 为 WebSocket 提供了 备选方案。但无论哪种场景,对于实际应用来说,这种通信形式层级过低。
    STOMP协议,来为浏览器 和 server 间的 通信增加适当的消息语义。

    2)WebSocket、SockJs、STOMP三者关系

    简而言之,WebSocket 是底层协议,SockJS 是WebSocket 的备选方案,也是底层协议,
    而 STOMP 是基于 WebSocket(SockJS)的上层协议。

    1、HTTP协议解决了 web 浏览器发起请求以及 web 服务器响应请求的细节,假设 HTTP 协议 并不存在,只能使用 TCP 套接字来 编写 web 应用。

    2、直接使用 WebSocket(SockJS) 就很类似于 使用 TCP 套接字来编写 web 应用,因为没有高层协议,就需要我们定义应用间所发送消息的语义,还需要确保连接的两端都能遵循这些语义;

    3、同HTTP在TCP 套接字上添加请求-响应模型层一样,STOMP在WebSocket 之上提供了一个基于帧的线路格式层,用来定义消息语义;

    代码结构

    广播模式:发送、订阅、配置

    pom.xml
    <dependency>
    	<groupId>org.springframework.boot</groupId>
    	<artifactId>spring-boot-starter-websocket</artifactId>
    </dependency>
    
    WebSocketConfig
    package com.test.websocket.config;
    
    import org.springframework.context.annotation.Configuration;
    import org.springframework.messaging.simp.config.MessageBrokerRegistry;
    import org.springframework.web.socket.config.annotation.*;
    
    /*
     * 通过@EnableWebSocketMessageBroker注解开启使用STOMP协议来传输基于代理(message broker)的消息,
     * 这时控制器支持使用@MessageMapping
     * 就像使用@RequestMapping一样
     */
    @Configuration
    @EnableWebSocketMessageBroker
    public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
        /**
         * 将"/endpointWisely"路径注册为STOMP端点,这个路径与发送和接收消息的目的路径有所不同
         * 这是一个端点,客户端在订阅或发布消息到目的地址前,要连接该端点,
         */
    
        @Override
        public void registerStompEndpoints(StompEndpointRegistry registry) {//注册STOMP协议的节点(endpoint),并映射的指定的URL
    //        registry.addEndpoint("/webServer").withSockJS();
    //        registry.addEndpoint("/queueServer").withSockJS();//注册两个STOMP的endpoint,分别用于广播和点对点
            registry.addEndpoint("/logserver").withSockJS();//注册一个STOMP的endpoint,并指定使用SockJS协议
            //registry.addEndpoint("/hello").setAllowedOrigins("*").withSokJS();
            //这个和客户端创建连接时的url有关,其中setAllowedOrigins()方法表示允许连接的域名,withSockJS()方法表示支持以SockJS方式连接服务器。
        }
    
        /**
         * 配置了一个简单的消息代理,如果不重载,默认情况下回自动配置一个简单的内存消息代理,用来处理以"/topic"为前缀的消息。
         * 这里重载configureMessageBroker()方法,
         * 消息代理将会处理前缀为"/topic"的消息。
         */
        @Override
        public void configureMessageBroker(MessageBrokerRegistry registry) {//配置消息代理(Message Broker)
            registry.enableSimpleBroker("/topic");//广播式应配置一个/topic消息代理
            ////topic用来广播,user用来实现p2p
        }
        /* PS
         * registry.enableSimpleBroker("/topic", "/user");这句话表示在topic和user这两个域上可以向客户端发消息。
         * registry.setUserDestinationPrefix("/user");这句话表示给指定用户发送一对一的主题前缀是"/user"。
         * registry.setApplicationDestinationPrefixes("/app");这句话表示客户单向服务器端发送时的主题上面需要加"/app"作为前缀。
         */
    }
    
    WebSocketServerJob
    package com.test.websocket.job;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.jms.annotation.JmsListener;
    import org.springframework.messaging.simp.SimpMessagingTemplate;
    import org.springframework.scheduling.annotation.Scheduled;
    import org.springframework.stereotype.Component;
    
    import java.util.Date;
    
    @Component
    public class WebSocketServerJob {
        @Autowired
        private SimpMessagingTemplate simpMessagingTemplate;
    
    //    @Scheduled(fixedRate = 1000)
    //    public void sendBroadCaseMessage(){
    //        System.out.println("来自服务端的消息");
    //        simpMessagingTemplate.convertAndSend("/topic/getResponse",new Date());
    //    }
    
        @JmsListener(destination = "USER_BEHAVIOR_UOLOADLOG")
        public void receiveQueue(String text) {
            System.out.println("receive from topic");
            simpMessagingTemplate.convertAndSend("/topic/getResponse",text);
        }
    }
    
    html
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <script src="jquery-3.4.1.js"></script>
        <script src="sockjs.js"></script>
        <script src="stomp.js"></script>
    </head>
    <body>
    <div id="msg"></div>
    
    <script>
        var socket = new SockJS("/logserver");
        stompClient = Stomp.over(socket);
        stompClient.connect({}, function(frame) {
            // setConnected(true);
            console.log('Connected: ' + frame);
            stompClient.subscribe('/topic/getResponse', function(response){
               console.log(response.body);
               $("#msg").prepend("<div style="border-top:1px solid #000">" +
                   response.body+"<br/>" +
                   "</div>")
            });
        });
    </script>
    </body>
    </html>
    
  • 相关阅读:
    【iOS开发】协议与委托 (Protocol and Delegate) 实例解析(转)
    Axure例——双击显示
    联动下拉菜单应用
    VB 9.0 和C# 3.0比较
    Office VBA进阶(二):如何在Access 2007里导入一个Excel sheet表
    Static Code Analysis Introduction
    VB future
    Office VBA进阶(三):如何合并Access里的多张表
    Office VBA进阶(四):如何在Access里创建一个Report
    Office VBA进阶(五):如何让EXCEL工作簿在浏览器里显示
  • 原文地址:https://www.cnblogs.com/xidianzxm/p/11161849.html
Copyright © 2020-2023  润新知