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>
posted @ 2019-07-10 09:34  xidianzxm  阅读(519)  评论(0编辑  收藏  举报