1. STOMP簡介
STOMP即Simple (or Streaming) Text Orientated Messaging Protocol,它是一個簡單的文本消息傳輸協議,提供了一個可互操作的連接格式,允許STOMP客戶端與任意STOMP消息代理(Broker)進行交互。STOMP協議由於設計簡單,易於開發客戶端,因此在多種語言和多種平臺上得到廣泛地應用。
2. 協議支持
- STOMP 1.0
- STOMP 1.1 (including heart-beating)
3. 下載JavaScript客戶端包文件
stomp.min.js,可直接使用於web項目中
4. STOMP API介紹
4.1 STOMP Frame(幀)
STOMP Over WebSocket 提供了一個直接從 STOMP frame到JavaScript object的映射。
Frame Object
Property |
Type |
Notes |
---|---|---|
command |
String |
name of the frame ("CONNECT", "SEND", etc.) |
headers |
JavaScript object |
|
body |
String |
command和headers屬性始終會被定義,但是當這個frame沒有頭部信息時,headers參數可以爲空,用{}表示。若這個frame沒有body(主體內容),body的值可以爲null。
4.2 STOMP客戶端創建(普通的WebSocket方式)
STOMP JavaScript客戶端將使用URL爲 ws:// 與STOMP server建立通信。
使用 Stomp.client(url) 來創建STOMP客戶端的js對象,如:
var url = "ws://localhost:61614/stomp";
var client = Stomp.client(url);
使用Stomp.client(url, protocols)可以覆蓋默認的subprotocols,如protocols爲['v10.stomp','v11.stomp'] 基於STOMP 1.0 & 1.1規範,第二個參數可以爲單獨的一個String類型,也可以爲一個String的數組類型。
4.3 STOMP客戶端創建(自定義WebSocket方式)
web瀏覽器支持不同的WebSocket協議版本,但是一些老版本的瀏覽器不支持WebSocket方式創建的js腳本,可以使用stomp.js,stomp.js會使用瀏覽器原生的WebSocket class來創建WebSocket。
使用Stomp.over(ws)方法,ws參數可以指定其他類型的WebSocket(如SockJS包裝的WebSocket)
<script src="http://cdn.sockjs.org/sockjs-0.3.min.js"></script>
<script>
// 使用SockJS實現而不是瀏覽器的本地實現
var ws = new SockJS(url);
var client = Stomp.over(ws);
[...]
</script>
4.4 在node.js應用中的使用
使用npm安裝stompjs
> npm install stompjs
在node.js程序中通過require導入stompjs模塊
var Stomp = require('stompjs');
建立一個基於TCP socket的連接到STOMP代理
var client = Stomp.overTCP('localhost', 61613);
建立一個基於Web Socket的連接到STOMP代理
var client = Stomp.overWS('ws://localhost:61614/stomp');
除了初始化不同,無論是瀏覽器還是node.js環境下,Stomp API都是相同的。
4.5 連接到服務端
當STOMP client創建好後,通過connect()方法進行與STOMP seerver的連接和認證,connect方法可接受多個參數來提供簡單的API。
client.connect(login, passcode, connectCallback);
client.connect(login, passcode, connectCallback, errorCallback);
client.connect(login, passcode, connectCallback, errorCallback, host);
注:login與passcode是String類型,connectCallback與errorCallback是回調函數,host爲String類型
如果需要附加一些其他的信息,可以通過傳遞一個headers參數。
client.connect(headers, connectCallback);
client.connect(headers, connectCallback, errorCallback);
注:headers爲map類型, connectCallback與errorCallback爲回調函數
如附加的headers參數
var headers = {
login: 'mylogin',
passcode: 'mypasscode',
// additional header
'client-id': 'my-client-id'
};
client.connect(headers, connectCallback);
也可使用{}來表示不附加任何headers參數
斷開連接時,調用disconnect方法,這個方法也是異步的,當斷開成功後會接收一個額外的回調函數的參數,如:
client.disconnect(function() {
alert("See you next time!");
};
當客戶端client斷開連接後,不能再發送和接收任何messages。
4.6 心跳檢測(heart-beating)
如果STOMP 代理接收的幀是STOMP 1.1協議時,默認心跳檢測是開啓的。
客戶端client對象有一個字段 heartbeat ,通過改變incoming和outgoing數值,來配置心跳頻率(默認頻率值爲:10000ms)
client.heartbeat.outgoing = 20000; // 客戶端每20000ms發送一次心跳檢測
client.heartbeat.incoming = 0; // client不接收serever端的心跳檢測
注:heart-beating是利用window.setInterval()去規律地發送heart-beats或者檢查服務端的heart-beats
4.7 發送消息
當客戶端與服務端連接成功後,可以調用send()方法來發送STOMP消息。這個方法必須有一個參數, 用來描述對應的STOMP的目的地。另外可以有兩個可選的參數:headers,object類型,包含額外的信息頭;body爲一個String類型的參數。
client.send("/queue/test", {priority: 9}, "Hello, STOMP");
代碼解釋:客戶端將發送一個STOMP的幀到 /queue/test 地址的目的地,攜帶的headers參數priority爲9,消息體爲Hello, STOMP
注:如果你想發送一個有消息體(body)的信息,也必須傳遞headers參數。如果沒有headers需要傳遞,可以用{}來表示,如:
client.send(destination, {}, body);
4.8 訂閱(Subscribe)和接收消息
瀏覽器接收一個消息,STOMP客戶端首先必須訂閱一個目標地址destination。
使用subscribe()方法訂閱,該方法接收兩個必選的參數destination String類型的目的地址和callback回調函數,還有一個可選的參數headers
var subscription = client.subscribe("/queue/test", callback);
subscribe()方法返回一個js對象,這個對象包含一個id屬性,對應這個這個客戶端的訂閱id。而unsubscribe()可以用來取消客戶端對這個目的地destination的訂閱。
默認情況下,如果沒有在headers參數中額外添加,這個庫會默認構建一個唯一的id。在傳遞headers這個參數時,可以使用你自己的id如:
var mysubid = '...';
var subscription = client.subscribe(destination, callback, { id: mysubid });
客戶端發送一個STOMP的訂閱幀到服務端,並註冊一個回調函數,每當服務端發送消息到客戶端時,客戶端都會調用回調函數,回調函數中的參數爲STOMP幀對象。
callback = function(message) {
// called when the client receives a STOMP message from the server
if (message.body) {
alert("got message with body " + message.body)
} else {
alert("got empty message");
}
});
subscribe()方法接收一個可選的參數headers,當訂閱一個目的地destination的時候可以附加該參數
var headers = {ack: 'client', 'selector': "location = 'Europe'"};
client.subscribe("/queue/test", message_callback, headers);
代碼解釋:該客戶端只接收匹配selector location = 'Europe'的消息,並且會確認接收到的message
注:如果想讓客戶端訂閱多個目的地destinations,可以使用同一個回調函數來接收messages
onmessage = function(message) {
// called every time the client receives a message
}
var sub1 = client.subscribe("queue/test", onmessage);
var sub2 = client.subscribe("queue/another", onmessage);
調用unsubscribe()方法可以終止接收messages
var subscription = client.subscribe(...);
...
subscription.unsubscribe();
4.9 JSON的支持
如果想發送和接收JSON對象的消息,可以通過JSON.stringify() 和 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);
};
4.10 消息確認
默認情況,在消息發送給客戶端之前,服務端會自動確認。
客戶端可以選擇通過訂閱一個目的地destination時設置一個ack,header爲client或client-individual來處理消息確認。
在下面這個例子,客戶端必須調用message.ack()來通知客戶端它已經接收了消息。
var subscription = client.subscribe("/queue/test",
function(message) {
// do something with the message
...
// and acknowledge it
message.ack();
},
{ack: 'client'}
);
使用nack()方法可以通知STOMP 1.1 代理,客戶端沒有消費該消息,和ack()方法的參數相同
4.11 事務(Transactions)
消息的發送確認可以在一個事務中處理。
通過調用客戶端自身的begin()方法來啓動事務,該方法有一個可選的參數transaction,String類型,唯一標識一個事務,如果沒有傳遞參數,那麼stompjs庫會自動生成。該方法會返回一個js對象,包含一個id屬性,對應該事務的ID。
另外兩個方法:
- commit()提交事務
- abort()終止事務
在一個事務中,客戶端可以在發送/接受消息時指定transaction id來設置transaction。
// start the transaction
var tx = client.begin();
// send the message in a transaction
client.send("/queue/test", {transaction: tx.id}, "message in a transaction");
// commit the transaction to effectively send the message
tx.commit();
注:如果在調用send()方法發送消息時未指定transaction頭信息,則該事務不起作用,如:
var txid = "unique_transaction_identifier";
// start the transaction
var tx = client.begin();
// oops! send the message outside the transaction
client.send("/queue/test", {}, "I thought I was in a transaction!");
tx.abort(); // Too late! the message has been sent
4.12 Debug調試
有一些測試代碼能有助於你知道庫發送或接收的是什麼,從而來調試程序。
客戶端可以將其debug屬性設置爲一個函數,傳遞一個字符串參數去觀察庫所有的debug語句。
client.debug = function(str) {
// append the debug log to a #debug div somewhere in the page using JQuery:
$("#debug").append(str + "\n");
};