STOMP 客戶端 API 整理


STOMP(Simple Text-Orientated Messaging Protocol) 面向消息的簡單文本協議
WebSocket是一個消息架構,不強制使用任何特定的消息協議,它依賴於應用層解釋消息的含義;
與處在應用層的HTTP不同,WebSocket處在TCP上非常薄的一層,會將字節流轉換為文本/二進制消息,因此,對於實際應用來說,WebSocket的通信形式層級過低,因此,可以在 WebSocket 之上使用 STOMP協議,來為瀏覽器 和 server間的 通信增加適當的消息語義。

如何理解 STOMP 與 WebSocket 的關系:
1) HTTP協議解決了 web 瀏覽器發起請求以及 web 服務器響應請求的細節,假設 HTTP 協議 並不存在,只能使用 TCP 套接字來 編寫 web 應用,你可能認為這是一件瘋狂的事情;
2) 直接使用 WebSocket(SockJS) 就很類似於 使用 TCP 套接字來編寫 web 應用,因為沒有高層協議,就需要我們定義應用間所發送消息的語義,還需要確保連接的兩端都能遵循這些語義;
3) 同 HTTP 在 TCP 套接字上添加請求-響應模型層一樣,STOMP 在 WebSocket 之上提供了一個基於幀的線路格式層,用來定義消息語義;
STOMP幀

STOMP幀由命令,一個或多個頭信息、一個空行及負載(文本或字節)所組成;
其中可用的COMMAND 包括: CONNECT、SEND、SUBSCRIBE、UNSUBSCRIBE、BEGIN、COMMIT、ABORT、ACK、NACK、DISCONNECT;
例:發送消息

    SEND
    destination:/queue/trade
    content-type:application/json
    content-length:44
    {“action”:”BUY”,”ticker”:”MMM”,”shares”,44}^@

 訂閱消息

 SUBSCRIBE
    id:sub-1
    destination:/topic/price.stock.*
    ^@

服務器進行廣播消息

   MESSAGE
    message-id:nxahklf6-1
    subscription:sub-1
    destination:/topic/price.stock.MMM
    {“ticker”:”MMM”,”price”:129.45}^@

 客戶端 API
引入stomp.js
<script type="application/javascript" src="http://cdn.bootcss.com/stomp.js/2.3.3/stomp.min.js"></script>
發起連接
客戶端可以通過使用Stomp.js和sockjs-client連接

// 建立連接對象(還未發起連接)
var socket=new SockJS("/spring-websocket-portfolio/portfolio");
// 獲取 STOMP 子協議的客戶端對象
var stompClient = Stomp.over(socket);
// 向服務器發起websocket連接並發送CONNECT幀
stompClient.connect({},function connectCallback (frame) {
    // 連接成功時(服務器響應 CONNECTED 幀)的回調方法
        document.getElementById("state-info").innerHTML = "連接成功";
        console.log('已連接【' + frame + '】');
        stompClient.subscribe('/topic/getResponse', function (response) {
            showResponse(response.body);
        });
    },
function errorCallBack (error) {
    // 連接失敗時(服務器響應 ERROR 幀)的回調方法
        document.getElementById("state-info").innerHTML = "連接失敗";
        console.log('連接失敗【' + error + '】');
    }
);
//1) socket連接對象也可通過WebSocket(不通過SockJS)連接
var socket=new WebSocket("/spring-websocket-portfolio/portfolio");
//2) stompClient.connect()方法簽名:
client.connect(headers, connectCallback, errorCallback);
//其中headers表示客戶端的認證信息,如:
var headers = {
  login: 'mylogin',
  passcode: 'mypasscode',
  // additional header
  'client-id': 'my-client-id'
};若無需認證,直接使用空對象 “{}” 即可;
connectCallback 表示連接成功時(服務器響應 CONNECTED 幀)的回調方法;
errorCallback 表示連接失敗時(服務器響應 ERROR 幀)的回調方法,非必須;
//斷開連接   若要從客戶端主動斷開連接,可調用 disconnect() 方法
client.disconnect(function () {
   alert("See you next time!");
}
//該方法為異步進行,因此包含了回調參數,操作完成時自動回調;

心跳機制
若使用STOMP 1.1 版本,默認開啟了心跳檢測機制,可通過client對象的heartbeat field進行配置(默認值都是10000 ms):
client.heartbeat.outgoing = 20000;  // client will send heartbeats every 20000ms
client.heartbeat.incoming = 0;      // client does not want to receive heartbeats from the server
發送信息

//連接成功后,客戶端可使用 send() 方法向服務器發送信息:
client.send(destination url[, headers[, body]]);
/*其中destination url 為服務器 controller中 @MessageMapping 中匹配的URL,字符串,必須參數;
headers 為發送信息的header,JavaScript 對象,可選參數;
body 為發送信息的 body,字符串,可選參數;例:*/
client.send("/queue/test", {priority: 9}, "Hello, STOMP");
client.send("/queue/test", {}, "Hello, STOMP");

訂閱、接收信息
STOMP 客戶端要想接收來自服務器推送的消息,必須先訂閱相應的URL,即發送一個 SUBSCRIBE 幀,然后才能不斷接收來自服務器的推送消息;
訂閱和接收消息通過 subscribe() 方法實現:

subscribe(destination url, callback[, headers])
/*其中destination url 為服務器 @SendTo 匹配的 URL,字符串;
callback 為每次收到服務器推送的消息時的回調方法,該方法包含參數 message;
headers 為附加的headers該方法返回一個包含了id屬性的 JavaScript 對象,可作為 unsubscribe() 方法的參數;*/

取消訂閱

var subscription = client.subscribe(...);
subscription.unsubscribe();

JSON 支持
STOMP 幀的 body 必須是 string 類型,若希望接收/發送 json 對象,可通過 JSON.stringify() and JSON.parse() 實現;

var quote = {symbol: 'APPL', value: 195.46};
client.send("/topic/stocks", {}, JSON.stringify(quote));
client.subcribe("/topic/stocks", function(message) {
var quote = JSON.parse(message.body);
alert(quote.symbol + " is at " + quote.value);
});

事務支持
STOMP 客戶端支持在發送消息時用事務進行處理:
可以將消息的發送和確認接收放在一個事務中。客戶端調用自身的begin()方法就可以開始啟動事務了,begin()有一個可選的參數transaction,一個唯一的可標識事務的字符串。如果沒有傳遞這個參數,那么庫會自動構建一個。這個方法會返回一個object。這個對象有一個id屬性對應這個事務的ID,還有兩個方法:commit()提交事務、abort()中止事務。在一個事務中,客戶端可以在發送/接受消息時指定transaction id來設置transaction。

var tx = client.begin();
client.send("/queue/test", {transaction: tx.id}, "message in a transaction");
tx.commit();

如果你在調用send()方法發送消息的時候忘記添加transction header,那么這不會稱為事務的一部分,這個消息會直接發送,不會等到事務完成后才發送。

調試

有一些測試代碼能有助於你知道庫發送或接收的是什么,從而來調試程序。客戶端可以將其debug屬性設置為一個函數,傳遞一個字符串參數去觀察庫所有的debug語句。默認情況,debug消息會被記錄在在瀏覽器的控制台。

client.debug = function(str) { $("#debug").append(str + "\n"); };

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM