Stomp Over Websocket文档

媒介

前两天整理了websocket的材料,本日就把上次没说完的Stomp.js好好说一说~
Stomp Over Webscoket参考文档:http://jmesnil.net/stomp-webs…
本文为参考文档的部份翻译,手艺不佳,若有失误请斧正。
本文转载自个人博客:http://lsxj615.com/2016/08/17…

什么是Stomp

STOMP即Simple (or Streaming) Text Orientated Messaging Protocol,简朴(流)文本定向音讯协定,它供应了一个可互操纵的衔接花样,许可STOMP客户端与恣意STOMP音讯代办(Broker)举行交互。STOMP协定由于设想简朴,易于开辟客户端,因此在多种语言和多种平台上获得广泛地运用。

协定支撑

该库支撑多种版本的STOMP协定:

下载STOMP.JS

你能够下载 stomp.js 并在你本身的WEB运用顺序中运用。
供应了多种版本也能够直接用于临盆。
这个js文件由CoffeeScript文件构建,请检察Contribute部份下载源码或阅读 annote source code

服务端请求

这个库不是纯真的Stomp 客户端。它旨在WebSockets上运转而不是TCP。基本上,WebSocket协定须要在阅读器客户端和服务端之间举行握手,确保阅读器的“same-origin”(同源)平安模子依然有用。

这意味着该库不能衔接通例的STOMP代办,由于Websocket初始化的握手不是STOMP协定的一部份,他们不能明白从而会谢绝衔接。

有一些正在举行的事情增加了WebSocket支撑STOMP代办,从而他们能够在WebSocket协定上吸收STOMP衔接。

HornetQ

HornetQ是由Red Hat and JBoss建立的开源音讯体系.

要使HornetQ支撑STOMP Over WebSocket,下载最新版本并按照以下步骤实行:

$ cd hornetq-x.y.z/examples/jms/stomp-websockets
$ mvn clean install
...
INFO: HQ221020: Started Netty Acceptor version 3.6.2.Final-c0d783c         localhost:61614 for STOMP_WS protocol
Apr 15, 2013 1:15:33 PM org.hornetq.core.server.impl.HornetQServerImpl$SharedStoreLiveActivation run
INFO: HQ221007: Server is now live
Apr 15, 2013 1:15:33 PM org.hornetq.core.server.impl.HornetQServerImpl start
INFO: HQ221001: HornetQ Server version 2.3.0.CR2 (black'n'yellow2, 123) [c9e29e45-a5bd-11e2-976a-b3fef7ceb5df]

此时HornetQ已开启了,而且61614在端口监听STOMP over WebSocket
它从URL为ws://localhost:61614/stomp 吸收WebSocket的衔接。

设置文档

ActiveMQ

设置文档

ActiveMQ Apollo

设置文档

RabbitMQ

设置文档

Stilts & Torquebox

Stilts 是一个STOMP原生的音讯框架。

TorqueBox 运用Stilts去供应它的Websockets and STOMP stack

Stomp API

STOMP 帧(Frame)

STOMP Over WebSocket 供应了一个直接从Stomp Frame映射到 Javascript 对象的体式格局。
Stomp Frame帧花样以下:

PropertyTypeNotes
commandStringname of the frame (“CONNECT”, “SEND”, etc.)
headersJavaScript object
bodyString

commandheaders属性一直会被定义,不过当这个frame没有头部时,headers能够为空。若这个frame没有bodybody的值能够为null

建立STOMP客户端

在web阅读器中运用一般的Web Socket

STOMP javascript 客户端会运用ws://的URL与STOMP 服务端举行交互。

为了建立一个STOMP客户端js对象,你须要运用Stomp.client(url),而这个URL衔接着服务端的WebSocket的代办:

var url = "ws://localhost:61614/stomp";
var client = Stomp.client(url);

Stomp.client(url, protocols)也能够用来掩盖默许的subprotocols。第二个参数能够是一个字符串或一个字符串数组去指定多个subprotocols

在web阅读器中运用定制的WebSocket

阅读器供应了差异的WebSocket的协定,一些老的阅读器不支撑WebSocket的剧本或许运用别的名字。默许下,stomp.js会运用阅读器原生的WebSocket class去建立WebSocket。

然则应用Stomp.over(ws)这个要领能够运用其他范例的WebSockets。这个要领获得一个满足WebSocket定义的对象。

比方,能够运用由SockJS完成的Websocket:

<script src="http://cdn.sockjs.org/sockjs-0.3.min.js"></script>
<script>
    // use SockJS implementation instead of the browser's native implementation
    var ws = new SockJS(url);
    var client = Stomp.over(ws);
    [...]
</script>

假如运用原生的Websockets就运用Stomp.client(url),假如须要运用其他范例的Websocket(比方由SockJS包装的Websocket)就运用Stomp.over(ws)

除了初始化有差异,Stomp API在这两种体式格局下是雷同的。

node.js顺序中

经由过程stompjs npm package一样也能够在node.js顺序中运用这个库。

$ npm install stompjs

在node.jsapp中, require这个模块:

var Stomp = require('stompjs');

为了与建立在TCP socket的STOMP-broker衔接,运用Stomp.overTCP(host, port)要领。

var client = Stomp.overTCP('localhost', 61613);

为了与建立在Web Socket的STOMP broker衔接,运用Stomp.overWS(url)要领。

var client = Stomp.overWS('ws://localhost:61614/stomp');

除了初始化差异,无论是阅读器照样node.js环境下,Stomp API都是雷同的。

衔接服务端

一旦Stomp 客户端建立了,必须挪用它的connect()要领去衔接,从而Stomp服务端举行考证。这个要领须要两个参数,用户的登录和暗码凭据。

这类状况下,客户端会运用Websocket翻开衔接,并发送一个CONNECT frame

这个衔接是异步举行的:你不能保证当这个要领返回时是有用衔接的。为了晓得衔接的效果,你须要一个回调函数。

var connect_callback = function() {
    // called back after the client is connected and authenticated to the STOMP server
};

然则假如衔接失利会发作什么呢?connect()要领吸收一个可选的参数(error_callback),当客户端不能衔接上服务端时,这个回调函数error_callback会被挪用,该函数的参数为对应的毛病对象。

var error_callback = function(error) {
    // display the error's message header:
    alert(error.headers.message);
};

在大多数状况下,connect()要领可吸收差异数目的参数来供应简朴的API:

client.connect(login, passcode, connectCallback);
client.connect(login, passcode, connectCallback, errorCallback);
client.connect(login, passcode, connectCallback, errorCallback, host);

loginpasscode是strings,connectCallbackerrorCallback则是functions。(有些brokers(代办)还须要通报一个host(String范例)参数。)

假如你须要附加一个headers头部,connect要领还吸收其他两种情势的参数:

client.connect(headers, connectCallback);
client.connect(headers, connectCallback, errorCallback);

headermap情势,connectCallbackerrorCallback为functions。

须要注重:假如你运用上述这类体式格局,你须要自行在headers增加login,passcode(以至host):

var headers = {
    login: 'mylogin',
    passcode: 'mypasscode',
    // additional header
    'client-id': 'my-client-id'
};
client.connect(headers, connectCallback);

断开衔接时,挪用disconnect要领,这个要领也是异步的,当断开胜利后会吸收一个分外的回调函数的参数。以下所示。

client.disconnect(function() {
    alert("See you next time!");
};

当客户端与服务端断开衔接,就不会再发送或吸收音讯了。

Heart-beating

假如STOMP broker(代办)吸收STOMP 1.1版本的帧,heart-beating是默许启用的。heart-beating也就是频次,incoming是吸收频次,outgoing是发送频次。

经由过程转变incomingoutgoing能够变动客户端的heart-beating(默许为10000ms):

client.heartbeat.outgoing = 20000; 
// client will send heartbeats every 20000ms
client.heartbeat.incoming = 0;
// client does not want to receive heartbeats
// from the server

heart-beating是应用window.setInterval()去规律地发送heart-beats或许搜检服务端的heart-beats

发送音讯

当客户端与服务端衔接胜利后,能够挪用send()来发送STOMP音讯。这个要领必须有一个参数,用来形貌对应的STOMP的目的地。别的能够有两个可选的参数:headersobject范例包括分外的信息头部;body,一个String范例的参数。

client.send("/queue/test", {priority: 9}, "Hello, STOMP");

client会发送一个STOMP发送帧给/queue/test,这个帧包括一个设置了priority为9的header和内容为“Hello, STOMP”的body

假如你想发送一个有body的信息,也必须通报headers参数。假如没有headers须要通报,那末就传{}即可,以下所示:

client.send(destination, {}, body);

定阅(Subscribe)和吸收(receive)音讯

为了在阅读器中吸收音讯,STOMP客户端必须先定阅一个目的地destination

你能够运用subscribe()去定阅。这个要领有2个必须的参数:目的地(destination),回调函数(callback);另有一个可选的参数headers。个中destination是String范例,对应目的地,回调函数是伴随着一个参数的function范例。

var subscription = client.subscribe("/queue/test", callback);

subscribe()要领返回一个object,这个object包括一个id属性,对应这个这个客户端的定阅ID。而unsubscribe()能够用来作废客户端对这个目的地destination的定阅。

默许状况下,假如没有在headers分外增加,这个库会默许构建一个举世无双的ID。在通报headers这个参数时,能够运用你本身的ID:

var mysubid = '...';
var subscription = client.subscribe(destination, callback, { id: mysubid });

这个客户端会向服务端发送一个STOMP定阅帧(SUBSCRIBE frame)并注册回调事宜。每次服务端向客户端发送音讯时,客户端都邑轮番挪用回调函数,参数为对应音讯的STOMP帧对象(Frame object)。以下所示:

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参数用来标识附加的头部。

var headers = {ack: 'client', 'selector': "location = 'Europe'"};

client.subscribe("/queue/test", message_callback, headers);

这个客户端指定了它会确认吸收的信息,只吸收相符这个selector : location = 'Europe'的音讯。

假如想让客户端定阅多个目的地,你能够在吸收一切信息的时刻挪用雷同的回调函数:

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)

假如要中断吸收音讯,客户端能够在subscribe()返回的object对象挪用unsubscribe()来完毕吸收。

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

...

subscription.unsubscribe();

支撑JSON

STOMP音讯的body必须为字符串。假如你须要发送/吸收JSON对象,你能够运用JSON.stringify()JSON.parse()去转换JSON对象。

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);
};

Acknowledgment(确认)

默许状况,在音讯发送给客户端之前,服务端会自动确认(acknowledged)。

客户端能够挑选经由过程定阅一个目的地时设置一个ack headerclientclient-individual来处置惩罚音讯确认。

在下面这个例子,客户端必须挪用message.ack()来关照服务端它已吸收了音讯。

var subscription = client.subscribe("/queue/test",
    function(message) {
        // do something with the message
        ...
        // and acknowledge it
        message.ack();
    },
    {ack: 'client'}
);

ack()吸收headers参数用来附加确认音讯。比方,将音讯作为事件(transaction)的一部份,当请求吸收音讯时实在代办(broker)已将ACK STOMP frame处置惩罚了。

var tx = client.begin();
message.ack({ transaction: tx.id, receipt: 'my-receipt' });
tx.commit();

nack()也能够用来关照STOMP 1.1.brokers(代办):客户端不能消耗这个音讯。与ack()要领的参数雷同。

事件(Transactions)

能够在将音讯的发送和确认吸收放在一个事件中。

客户端挪用本身的begin()要领就能够最先启动事件了,begin()有一个可选的参数transaction,一个唯一的可标识事件的字符串。假如没有通报这个参数,那末库会自动构建一个。

这个要领会返回一个object。这个对象有一个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()要领发送音讯的时刻遗忘增加transction header,那末这不会称为事件的一部份,这个音讯会直接发送,不会比及事件完成后才发送。

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

调试(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");
};

默许状况,debug音讯会被纪录在在阅读器的控制台。

    原文作者:lsxj
    原文地址: https://segmentfault.com/a/1190000006617344
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞