参考教程:http://jmesnil.net/stomp-websocket/doc/ javascript
在使用 stomp.js 时,能找到的较完整的 API 说明基本都是英文,中文资料比较少,所以,参考上边的教程作了如下的笔记和总结css
STOMP(Simple Text-Orientated Messaging Protocol) 面向消息的简单文本协议html
WebSocket是一个消息架构,不强制使用任何特定的消息协议,它依赖于应用层解释消息的含义;java
与处在应用层的HTTP不一样,WebSocket处在TCP上很是薄的一层,会将字节流转换为文本/二进制消息,所以,对于实际应用来讲,WebSocket的通讯形式层级太低,所以,能够在 WebSocket 之上使用 STOMP协议,来为浏览器 和 server间的 通讯增长适当的消息语义。web
如何理解 STOMP 与 WebSocket 的关系:
1) HTTP协议解决了 web 浏览器发起请求以及 web 服务器响应请求的细节,假设 HTTP 协议 并不存在,只能使用 TCP 套接字来 编写 web 应用,你可能认为这是一件疯狂的事情;
2) 直接使用 WebSocket(SockJS) 就很相似于 使用 TCP 套接字来编写 web 应用,由于没有高层协议,就须要咱们定义应用间所发送消息的语义,还须要确保链接的两端都能遵循这些语义;
3) 同 HTTP 在 TCP 套接字上添加请求-响应模型层同样,STOMP 在 WebSocket 之上提供了一个基于帧的线路格式层,用来定义消息语义;spring
STOMP帧由命令,一个或多个头信息、一个空行及负载(文本或字节)所组成;sql
其中可用的COMMAND 包括:json
CONNECT、SEND、SUBSCRIBE、UNSUBSCRIBE、BEGIN、COMMIT、ABORT、ACK、NACK、DISCONNECT;api
例:
发送消息浏览器
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}^@
引入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
// The heart-beating is using window.setInterval() to regularly send heart-beats and/or check server heart-beats
链接成功后,客户端可以使用 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,JavaScript 对象;什么做用?
该方法返回一个包含了id属性的 JavaScript 对象,可做为 unsubscribe() 方法的参数;
例:
var headers = {ack: 'client', 'selector': "location = 'Europe'"};
var callback = function(message) {
if (message.body) {
alert("got message with body " + message.body)
} else {
alert("got empty message");
}
});
var subscription = client.subscribe("/queue/test", callback, headers);
var subscription = client.subscribe(...);
subscription.unsubscribe();
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 客户端支持在发送消息时用事务进行处理:
举例说明:
// start the transaction // 该方法返回一个包含了事务 id、commit()、abort() 的JavaScript 对象 var tx = client.begin();
// send the message in a transaction
// 最关键的在于要在 headers 对象中加入事务 id,若没有添加,则会直接发送消息,不会以事务进行处理
client.send("/queue/test", {transaction: tx.id}, "message in a transaction");
// commit the transaction to effectively send the message tx.commit();
// tx.abort();
STOMP 客户端默认将传输过程当中的全部 debug 信息以 console.log() 形式输出到客户端浏览器中,也可经过如下方式输出到 DOM 中:
client.debug = function(str) {
// str 参数即为 debug 信息
// append the debug log to a #debug div somewhere in the page using JQuery:
$("#debug").append(str + "\n");
};
这一部份内容看的不是很理解,所以直接将原文放在这里了,待补充。
By default, STOMP messages will be automatically acknowledged by the server before the message is delivered to the client.
The client can chose instead to handle message acknowledgement by subscribing to a destination and specify a ack header set to client or client-individual.
In that case, the client must use the message.ack() method to inform the server that it has acknowledge the message.
var subscription = client.subscribe("/queue/test",
function(message) {
// do something with the message
...
// and acknowledge it
message.ack();
},
{ack: 'client'}
);
The ack() method accepts a headers argument for additional headers to acknowledge the message. For example, it is possible to acknowledge a message as part of a transaction and ask for a receipt when the ACK STOMP frame has effectively be processed by the broker: var tx = client.begin(); message.ack({ transaction: tx.id, receipt: ‘my-receipt’ }); tx.commit(); The nack() method can also be used to inform STOMP 1.1 brokers that the client did not consume the message. It takes the same arguments than the ack() method.