• 前端 Websocket + Stomp.js 的使用


    什么是Stomp

    STOMP即Simple (or Streaming) Text Orientated Messaging Protocol,简单(流)文本定向消息协议,它提供了一个可互操作的连接格式,允许STOMP客户端与任意STOMP消息代理(Broker)进行交互。STOMP协议由于设计简单,易于开发客户端,因此在多种语言和多种平台上得到广泛地应用。

    服务端要求 

    这个库不是单纯的Stomp 客户端。它旨在WebSockets上运行而不是TCP。基本上,WebSocket协议需要在浏览器客户端和服务端之间进行握手,确保浏览器的“same-origin”(同源)安全模型仍然有效。

    这意味着该库不能连接常规的STOMP代理,因为Websocket初始化的握手不是STOMP协议的一部分,他们不能理解从而会拒绝连接。

    有一些正在进行的工作添加了WebSocket支持STOMP代理,从而他们可以在WebSocket协议上接受STOMP连接。

    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的代理:

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

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

    连接服务端

    一旦Stomp 客户端建立了,必须调用它的connect()方法去连接,从而Stomp服务端进行验证。这个方法需要两个参数,用户的登录和密码凭证。

    这种情况下,客户端会使用Websocket打开连接,并发送一个CONNECT frame

    这个连接是异步进行的:你不能保证当这个方法返回时是有效连接的。为了知道连接的结果,你需要一个回调函数。

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

    但是如果连接失败会发生什么呢?connect()方法接受一个可选的参数(error_callback),当客户端不能连接上服务端时,这个回调函数error_callback会被调用,该函数的参数为对应的错误对象。 

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

    在大多数情况下,connect()方法可接受不同数量的参数来提供简单的API: 

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

    loginpasscode是strings,connectCallbackerrorCallback则是functions。(有些brokers(代理)还需要传递一个host(String类型)参数。)

    如果你需要附加一个headers头部,connect方法还接受其他两种形式的参数:

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

    headermap形式,connectCallbackerrorCallback为functions。

    需要注意:如果你使用上述这种方式,你需要自行在headers添加login,passcode(甚至host):

    1. var headers = {
    2. login: 'mylogin',
    3. passcode: 'mypasscode',
    4. // additional header
    5. 'client-id': 'my-client-id'
    6. };
    7. client.connect(headers, connectCallback);

    断开连接时,调用disconnect方法,这个方法也是异步的,当断开成功后会接收一个额外的回调函数的参数。如下所示。 

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

    当客户端与服务端断开连接,就不会再发送或接收消息了。 

    发送消息

    当客户端与服务端连接成功后,可以调用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:

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

    这个客户端会向服务端发送一个STOMP订阅帧(SUBSCRIBE frame)并注册回调事件。每次服务端向客户端发送消息时,客户端都会轮流调用回调函数,参数为对应消息的STOMP帧对象(Frame object)。如下所示: 

    1. callback = function(message) {
    2. // called when the client receives a STOMP message from the server
    3. if (message.body) {
    4. alert("got message with body " + message.body)
    5. } else {
    6. alert("got empty message");
    7. }
    8. });

    subscribe()方法,接受一个可选的headers参数用来标识附加的头部。 

    1. var headers = {ack: 'client', 'selector': "location = 'Europe'"};
    2. client.subscribe("/queue/test", message_callback, headers);

    这个客户端指定了它会确认接收的信息,只接收符合这个selector : location = 'Europe'的消息。

    如果想让客户端订阅多个目的地,你可以在接收所有信息的时候调用相同的回调函数:

    1. onmessage = function(message) {
    2. // called every time the client receives a message
    3. }
    4. var sub1 = client.subscribe("queue/test", onmessage);
    5. var sub2 = client.subscribe("queue/another", onmessage)

     如果要中止接收消息,客户端可以在subscribe()返回的object对象调用unsubscribe()来结束接收。

    1. var subscription = client.subscribe(...);
    2. ...
    3. subscription.unsubscribe();
  • 相关阅读:
    4、数据完整性
    GoogLeNet 08
    FAILED: HiveException java.lang.RuntimeException: Unable to instantiate
    A-Level经济真题每期一练(53)
    SpringBatch适配不同数据库的两种方法
    SpringMVC 学习(九)之拦截器
    [Vue3]Vue3基本概述
    Web字体的使用
    如何搭建一部引人入胜的短剧小程序
    【科普分享】linux服务器文件挂载技术介绍——mount
  • 原文地址:https://blog.csdn.net/m0_62118859/article/details/125515118