SpringWebsocket +Stomp+SockJS實現消息訂閱和推送

一、STOMP協議介紹

STOMP即Simple (or Streaming) Text Orientated Messaging Protocol,簡單(流)文本定向消息協議,它提供了一個可互操作的連接格式,允許STOMP客戶端與任意STOMP消息代理(Broker)進行交互。STOMP協議由於設計簡單,易於開發客戶端,因此在多種語言和多種平臺上得到廣泛地應用。

STOMP協議的前身是TTMP協議(一個簡單的基於文本的協議),專爲消息中間件設計。

STOMP是一個非常簡單和容易實現的協議,其設計靈感源自於HTTP的簡單性。儘管STOMP協議在服務器端的實現可能有一定的難度,但客戶端的實現卻很容易。例如,可以使用Telnet登錄到任何的STOMP代理,並與STOMP代理進行交互。

二、SockJS介紹

SockJS 是一個瀏覽器上運行的 JavaScript 庫,如果瀏覽器不支持 WebSocket,該庫可以模擬對 WebSocket 的支持,實現瀏覽器和 Web 服務器之間低延遲、全雙工、跨域的通訊通道。

三、websocket 是什麼?

是一種網絡通信協議,很多高級功能都需要它

四、爲什麼要使用websocket?

已經有了HTTP協議 爲撒還需要使用WebSocket 嘞?

HTTP 是客戶端請求服務端響應數據,但是我們如果想服務端給客戶端發送消息嘞?

於是乎就有了這種協議,客戶端,服務端可以雙向發送消息最典型的就是聊天系統

五、爲什麼需要stomp?

常規的websocket連接和普通的TCP基本上沒區別

所以STOMP在websocket上提供了一中基於幀線路格式(frame-based wire format)

簡單一點,就是在我們的websocket(TCP)上面加了一層協議,使雙方遵循這種協議來發送消息

 

服務端:/app,這裏訪問服務端,前綴通過設定的方式訪問

用戶:/user,這裏針對的是用戶消息的傳遞,針對於當前用戶進行傳遞。

其他消息:/topic、/queue,這兩種方式。都是定義出來用於訂閱服務端
 

需求

APP用戶發起申請操作,需要讓後臺管理系統部分人員感知(審覈提醒 消息提示)。

主要側重介紹下 服務器主動推送,由服務端來觸發。

WebSocket 主要能實現的場景

1、網頁聊天室

2、服務器消息實時通知

 

來吧,展示~

1.導入pom依賴

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

2.websocket配置 - WebSocketConfig

/**
 * 	通過EnableWebSocketMessageBroker 開啓使用STOMP協議來傳輸基於代理(message broker)的消息,此時瀏覽器支持使用@MessageMapping 就像支持@RequestMapping一樣。
 */
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {

    /**
    * 基於STOMP協議的WebSocket
    * endPoint 註冊協議節點,並映射指定的URl
    *
    * @param registry
    */
    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        // 註冊一個websocket端點,客戶端將使用它連接到我們的websocket服務器。
        registry.addEndpoint("/socket").setAllowedOrigins("*").withSockJS();
    }

    /**
    * 註冊相關服務
    * 配置消息代理(message broker)
    *
    * @param registry
    */
    @Override
    public void configureMessageBroker(MessageBrokerRegistry registry) {
        //定義了服務端接收地址的前綴,也即客戶端給服務端發消息的地址前綴
        registry.setApplicationDestinationPrefixes("/yifan");
        //定義了一個(或多個)客戶端訂閱地址的前綴信息,也就是客戶端接收服務端發送消息的前綴信息
        registry.enableSimpleBroker("/topic", "/user");
        // 點對點使用的訂閱前綴(客戶端訂閱路徑上會體現出來),不設置的話,默認也是/user/
        registry.setUserDestinationPrefix("/user/");
    }
}

介紹以上幾個相關的註解和方法:

  • @EnableWebSocketMessageBroker:開啓使用STOMP協議來傳輸基於代理(message broker)的消息,這時控制器支持使用@MessageMapping,就像使用@RequestMapping一樣。
  • AbstractWebSocketMessageBrokerConfigurer:繼承WebSocket消息代理的類,配置相關信息。
  • registry.addEndpoint("/endpointOyzc").setAllowedOrigins("*").withSockJS(); 添加一個訪問端點“/endpointGym”,客戶端打開雙通道時需要的url,允許所有的域名跨域訪問,指定使用SockJS協議。
  • registry.enableSimpleBroker("/topic","/user"); 配置一個/topic廣播消息代理和“/user”一對一消息代理
  • registry.setUserDestinationPrefix("/user");點對點使用的訂閱前綴(客戶端訂閱路徑上會體現出來),不設置的話,默認也是/user/

3.產生一個消息

@Controller
//@RequestMapping("/yifan/{user}")
@RequestMapping("yifan")
public class ChatController {

    @Autowired
    private SimpMessagingTemplate template;

    /* 接收消息     @SendToUser 誰發送的返回給誰  */
    @MessageMapping("/chatTo")
    public void apply(SocketMessage message){
        /* 發送給個人*/
        // template.convertAndSendToUser(userDO.toString(), "/topic/notifications", "新消息:" + notify.getTitle());
        /* 發送給全部*/
        template.convertAndSend("/topic/getResponse", new Response("客戶xxx發起申請,請及時處理!" ));
    }

    
    @MessageMapping("/chatTo") // 瀏覽器發送請求通過@messageMapping 映射/welcome 這個地址。
	@SendTo("/topic/getResponse") // 服務器端有消息時,會訂閱@SendTo 中的路徑的瀏覽器發送消息。
	public Response say(Message message) throws Exception {
		Thread.sleep(1000);
		return new Response("Welcome, " + message.getName() + "!");
	}
}

4.客戶端 網頁

需要準備

<script type="text/javascript">
    var stompClient = null;
    $(function () {
        connect();
    });

    function connect() {
        //連接SockJS的endpoint名稱爲"endpointOyzc"
        var sock = new SockJS("/endpointChat");
        var stomp = Stomp.over(sock);
        stomp.connect('guest', 'guest', function(frame) {

            /**
 訂閱了/user/queue/notifications 發送的消息,這裏雨在控制器的 convertAndSendToUser 定義的地址保持一致,

             *  這裏多用了一個/user,並且這個user 是必須的,使用user 纔會發送消息到指定的用戶。

             *  */
            stomp.subscribe("/user/queue/notifications", handleNotification);
            stomp.subscribe('/topic/getResponse', function (response) { //訂閱/topic/getResponse 目標發送的消息。這個是在控制器的@SendTo中定義的。
                toastr.options = {
                    "closeButton": true,
                    "debug": false,
                    "progressBar": true,
                    "positionClass": "toast-bottom-right",
                    "onclick": null,
                    "showDuration": "400",
                    "hideDuration": "1000",
                    "timeOut": "7000",
                    "extendedTimeOut": "1000",
                    "showEasing": "swing",
                    "hideEasing": "linear",
                    "showMethod": "fadeIn",
                    "hideMethod": "fadeOut"
                }
                toastr.info(JSON.parse(response.body).responseMessage);
            });
        });
        function handleNotification(message) {
            wrapper.notify();
            toastr.info(message.body);
        }
    }

</script>

分享參考文章:

https://blog.csdn.net/zhou4700219/article/details/53518788

https://blog.csdn.net/liyongzhi1992/article/details/81221103?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.nonecase&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.nonecase

https://blog.csdn.net/zhangdehua678/article/details/78913839?utm_medium=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.nonecase&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.nonecase

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章