天天看點

android消息推送服務端+用戶端_Java服務端推送消息有那麼難嗎?

場景:

今天項目經理交給我一個開發任務。如果有人在前台下了訂單就給背景倉庫管理一個發貨通知。也就是服務端觸發一個事件,推送消息到用戶端。

如果我用websocket來做還要搞個websocket伺服器,而且還 有不少配置。websocket是全雙工通信,單向通信簡直是殺雞用牛刀。用輪詢吧,浪費伺服器資源不說,還不一定實時,訂單處理慢了豈不是怠慢了客戶。有沒有别的選擇呢?當然有!

android消息推送服務端+用戶端_Java服務端推送消息有那麼難嗎?

1.SSE推送技術

SSE全稱Server-sent Events,是HTML 5 規範的一個組成部分,具體去MDN網站檢視相關文檔。該規範十分簡單,主要由兩個部分組成:第一個部分是伺服器端與浏覽器端之間的通訊協定,第二部分是在浏覽器端可供 JavaScript 使用的 EventSource 對象。通訊協定是基于純文字的簡單協定。伺服器響應的内容類型是“text/event-stream”。響應文本的内容可以看成是一個事件流,由不同的事件所組成。每個事件由類型和資料兩部分組成,同時每個事件可以有一個可選的辨別符。不同僚件的内容之間通過僅包含回車符和換行符的空行(“”)來分隔。每個事件的資料可能由多行組成。

android消息推送服務端+用戶端_Java服務端推送消息有那麼難嗎?

如上圖所示,每個事件之間通過空行來分隔。每一行都是由鍵值對組成。如果鍵為空則表示該行為注釋,會在處理時被忽略。例如第10行。

第1行表示一個隻包含資料的事件。會按照預設事件走(message事件)。第3-4行代表一個附帶eventID的事件。第6-8行代表一個自定義事件。第10-14行代表一個多行資料事件,多行資料由換行符連結

key定義有以下幾種:

  • data,表示該行包含的是資料。以 data 開頭的行可以出現多次。所有這些行都是該事件的資料。
  • event,表示該行用來聲明事件的類型。浏覽器在收到資料時,會産生對應類型的事件。預設提供三個标準事件(當然你可以自定義):
android消息推送服務端+用戶端_Java服務端推送消息有那麼難嗎?
  • id,表示該行用來聲明事件的辨別符。伺服器端傳回的資料中包含了事件的辨別符,浏覽器會記錄最近一次接收到的事件的辨別符。如果與伺服器端的連接配接中斷,當浏覽器端再次進行連接配接時,會通過 HTTP 頭“Last-Event-ID”來聲明最後一次接收到的事件的辨別符。伺服器端可以通過浏覽器端發送的事件辨別符來确定從哪個事件開始來繼續連接配接。
  • retry,表示該行用來聲明浏覽器在連接配接斷開之後進行再次連接配接之前的等待時間。

SSE隻适用于進階浏覽器,但是注意IE不直接支援。IE上的XMLHttpRequest對象不支援擷取部分的響應内容,是以不支援。每次總有IE,怪不得快被淘汰了。

2.SSE VS Websocket

  • SSE 隻能Server到Client單項,而Websocket是雙向通信。
  • SSE 比 Websocket 輕量。當然功能要簡單的多。開發便利,不牽涉協定更新問題。
  • SSE 天然支援斷線重連

3.Spring Mvc中的SSE

Spring Mvc對SSE進行了支援。如果你要聲明一個SSE連接配接。隻需要在你的控制器聲明一個如下接口:

android消息推送服務端+用戶端_Java服務端推送消息有那麼難嗎?

必須必須傳回SseEmitter對象,SseEmitter對象是Session級别的,如果你要點對點針對每個session要獨立存儲。如果你是廣播可以共用一個SseEmitter對象。按照SSE規範也必須聲明produces為"text/event-stream"。當你調用該接口的時候将建立起SSE連接配接。

你可以在另一個線程中調用SseEmitter的send方法向用戶端發送事件。你也可以在發送事件後調用complete方法來關閉SSE連接配接。

4.浏覽器端的EventSource

由于SSE 是HTML5規範。是以對于APP端必須有HTML才能支援。并且IE如果要支援需要使用一些相容開發包,比如polyfill庫。用戶端因為隻接受事件是以開發比較簡單:

  • 聲明用戶端連接配接, 初始化EventSource對象。
  • 編寫監聽器來監聽事件。
android消息推送服務端+用戶端_Java服務端推送消息有那麼難嗎?

今天介紹了SSE 服務端推送。和長輪訓、comet、websocket相比而言比較輕量級。在一些需要伺服器實時推送規模不大的業務場景實作更簡單點。相信看了本文後你會很快入門。在實際開發中要根據業務對這幾種推送進行技術選型。沒有最好的隻有最适合的。SSE對大多數開發者來說不夠熟悉。