美文网首页
Spring-boot-websocket

Spring-boot-websocket

作者: Shawn_Shawn | 来源:发表于2020-09-09 00:02 被阅读0次

    Spring-boot-websocket

    什么是WebSocket

    WebSocket是一种在单个TCP连接上进行全双工通信的协议。WebSocket使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在WebSocket API中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。

    与HTTP不同,WebSocket提供全双工通信。此外,WebSocket还可以在TCP之上实现消息流。TCP单独处理字节流,没有固有的消息概念。 在WebSocket之前,使用Comet可以实现全双工通信。但是Comet存在TCP握手和HTTP头的开销,因此对于小消息来说效率很低。WebSocket协议旨在解决这些问题。

    为什么使用WebSocket

    很多网站需要实现推送技术,所用的技术都是轮询,轮询是指由浏览器每隔一段时间(如每秒)向服务器发出HTTP请求,然后服务器返回最新的数据给客户端。这种传统的模式带来很明显的缺点,即浏览器需要不断的向服务器发出请求,然而HTTP请求与回复可能会包含较长的头部,其中真正有效的数据可能只是很小的一部分,所以这样会消耗很多带宽资源。WebSocket协议,能更好的节省服务器资源和带宽,并且能够更实时地进行通讯。

    WebSocket的优点

    • 较少的控制开销。在连接创建后,服务器和客户端之间交换数据时,用于协议控制的数据包头部相对较小。在不包含扩展的情况下,对于服务器到客户端的内容,此头部大小只有2至10字节(和数据包长度有关);对于客户端到服务器的内容,此头部还需要加上额外的4字节的掩码。相对于HTTP请求每次都要携带完整的头部,此项开销显著减少了。
    • 更强的实时性。由于协议是全双工的,所以服务器可以随时主动给客户端下发数据。相对于HTTP请求需要等待客户端发起请求服务端才能响应,延迟明显更少;即使是和Comet等类似的长轮询比较,其也能在短时间内更多次地传递数据。
    • 保持连接状态。与HTTP不同的是,Websocket需要先创建连接,这就使得其成为一种有状态的协议,之后通信时可以省略部分状态信息。而HTTP请求可能需要在每个请求都携带状态信息(如身份认证等)。
    • 更好的二进制支持。Websocket定义了二进制帧,相对HTTP,可以更轻松地处理二进制内容。
    • 可以支持扩展。Websocket定义了扩展,用户可以扩展协议、实现部分自定义的子协议。如部分浏览器支持压缩等。
    • 更好的压缩效果。相对于HTTP压缩,Websocket在适当的扩展支持下,可以沿用之前内容的上下文,在传递类似的数据时,可以显著地提高压缩率。

    常见的WebSocket使用场景

    1. 社交网站,在线聊天,在线教育,在线编程。。。
    2. 数据实时更新,例如股票实时更新,体育状况实时更新,弹幕。。。
    3. 一些框架,html页面修改了以后,浏览器也能实时刷新。例如webpack。

    如何集成spring boot + websocket

    服务端代码:

    1. pom.xml

      <dependencies>
        <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-websocket</artifactId>
        </dependency>
        <dependency>
          <groupId>com.google.guava</groupId>
          <artifactId>guava</artifactId>
        </dependency>
        <dependency>
          <groupId>org.projectlombok</groupId>
          <artifactId>lombok</artifactId>
        </dependency>
      </dependencies>
      
    2. configuration

      @Configuration
      @EnableWebSocket // 开启websocket
      @EnableWebSocketMessageBroker // WebSocketMessageBroker
      public class WebSocketConfiguration implements WebSocketMessageBrokerConfigurer {
      
        @Override
        public void registerStompEndpoints(StompEndpointRegistry registry) {
            // 对应js中 new SockJS("http://localhost:8080/ws"); 会注册这个埋点请求
          registry.addEndpoint("/ws").setAllowedOrigins("*").withSockJS();
        }
      
        @Override
        public void configureMessageBroker(MessageBrokerRegistry registry) {
            // 对应js中 stompClient.subscribe("/topic/message", callback) 
            // stompClient.subscribe("/user/1/message",callback)
          registry.enableSimpleBroker("/topic", "/user");
        }
      }
      
    3. job

      @Component
      public class WebSocketMessageJob {
      
        @Autowired private SimpMessagingTemplate template;
      
        @Scheduled(fixedRate = 1000)
        public void sendMessage() {
            // 广播
          template.convertAndSend("/topic/message", System.currentTimeMillis());
        }
      
        @Scheduled(fixedRate = 3000)
        public void sendMessageToUser() {
            // 指定用户推送
          template.convertAndSendToUser("2", "/message", System.currentTimeMillis());
        }
      }
      
    4. main

      @SpringBootApplication
      @EnableScheduling
      public class WebSocketApplication {
        public static void main(String[] args) {
          SpringApplication.run(WebSocketApplication.class, args);
        }
      }
      

    客户端代码:

    // 引入sockjs.min.js,stomp.js,jquery-3.5.1.js
    const sock = new SockJS("http://localhost:8080/ws");
      const stompClient = Stomp.over(sock);
      stompClient.connect({}, (frame) => {
        stompClient.subscribe("/topic/message", (response) => {
          server = JSON.parse(response.body);
          console.log(server);
        });
        stompClient.subscribe("/user/1/message", (response) => {
          server = JSON.parse(response.body);
          console.log(server);
        });
     });
    

    相关文章

      网友评论

          本文标题:Spring-boot-websocket

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