一、STOMP 简介

如果直接使用 WebSocket 会非常累,就像用 Socket 编写 Web 应用。没有高层级的交互协议,就需要我们定义应用间所发消息的语义,还需要确保连接的两端都能遵循这些语义。

如 HTTP 在 TCP 套接字之上添加了请求-响应模型层一样,STOMP 是在 WebSocket 之上提供了基于帧的线路格式层,用来定义消息的语义。

与 HTTP 请求和响应类似,STOMP 帧由命令、一个或多个头信息以及负载组成。像下面这段,就是发送数据的一个 STOMP 帧:

SEND
transaction:tx-0
destination:/app/hello
content-length:20 {"message":"Hello!"}

在这个示例中,STOMP 命令是 send,表明会发送一些内容。紧接着是三个头信息:一个表示消息的的事务机制,一个用来表示消息要发送到哪里的目的地,另外一个则包含了负载的大小。然后,紧接着是一个空行,STOMP 帧的最后是负载内容。

二、服务端实现

1、启用STOMP功能

STOMP 的消息根据前缀的不同分为三种。如下,以 /app 开头的消息都可以路由到带有 @Mapping 注解的方法中;以/topic 开头的消息都会发送到 STOMP 代理中,根据你所选择的 STOMP 代理不同,目的地的可选前缀也会有所限制;以 /user 开头的消息会将消息重路由到某个用户独有的目的地上。

添加依赖

<dependency>
<groupId>org.noear</groupId>
<artifactId>solon-net-stomp</artifactId>
</dependency>

添加端点监听,并设定 broker 目的地前缀

@ServerEndpoint("/demo")
public class DemoStompBroker extends StompBroker {
public DemoStompBroker() {
this.setBrokerDestinationPrefixes("/topic/");
}
}

2、处理来自客户端的STOMP消息

服务端处理客户端发来的 STOMP 消息,主要用的是 @Mapping 注解(和 MVC 开发一样),也可以增加 @Message 方式限有定注解。如下:

@Message //如果不加,同时匹配 http 及其它请求
@Mapping("/app/marco")
@To("*:/topic/marco")
public Shout greeting(Shout shout) throws Exception {
log.debug("接收到消息:" + shout.getMessage());
Shout s = new Shout();
s.setMessage("Polo!");
return s;
}

2.1 @Mapping 指定目的地是 /app/marco(我们将其约定为应用的目的地前缀)。

2.2 方法接收一个 Shout 参数,因为 Solon 的执行器根据内容类型自动会将 STOMP 消息的负载转换为 Shout 对象。

2.3 尤其注意,这个处理器方法有一个返回值,这个返回值并不是返回给客户端的,而是转发给消息代理的,如果客户端想要这个返回值的话,只能从消息代理订阅。@To 注解重写了消息代理的目的地,如果不指定@To,帧所发往的目的地会与触发处理器方法的目的地相同。

2.4 如果客户端就是想要服务端直接返回消息呢?听起来不就是HTTP做的事情!即使这样,STOMP 仍然为这种一次性的响应提供了支持,用的还是@Mapping 注解,与HTTP不同的是,这种请求-响应模式是异步的...

@Message
@Mapping("/app/getShout")
public Shout getShout(){
Shout shout = new Shout();
shout.setMessage("Hello STOMP");
return shout;
}

3、发送消息到客户端

3.1 在应用的任意地方发送消息

使用 StompEmitter 接口,可以实现自由的向任意目的地发送消息。

@Inject
private StompEmitter stompEmitter; /**
* 通过 http 接口,广播消息
*/
@Http
@Mapping("/broadcastShout")
public void broadcast(Context ctx, Shout shout) {
String json = ctx.renderAndReturn(shout); //渲染数据
stompEmitter.sendTo("/topic/shouts", json);
}

3.2 更多发送消息的方式

如果消息只想发送给特定的用户呢?或者发给当前用户?或者所有订阅用户?solon-net-stomp 给了两种方式来实现这种功能:

  • 一种是 StompEmitter 接口的 sendTo 方法。
  • 一种是 基于 @To 注解。
StompEmitter 接口 对应的 @To 注解 说明
@To("target:destination?") To 注解表达式(stomp 请求时有效)
sendToSession @To(".:/...")
@To(".")
发给当前客户端订阅者
sendToUser @To("user:/...")
@To("user")
发给特定用户订阅者
sendTo @To("*:/...")
@To("*")
发给代理,再转发给所有订阅者

4、处理消息异常

在处理消息的时候,有可能会出错并抛出异常。因为STOMP消息异步的特点,发送者可能永远也不会知道出现了错误。可以调整端点监听,添加 StompListener 实现。

@ServerEndpoint("/demo")
public class DemoStompBroker extends StompBroker implements StompListener{
public DemoStompBroker(){
//可选:添加鉴权监听器(此示例,用本类实现监听)
this.addListener(this);
this.setBrokerDestinationPrefixes("/topic/");
} @Override
public void onError(StompSession session, Throwable error) {
//可选:如果出错,反馈给客户端(比如用 "/user/app/errors")
getEmitter().sendToSession(session,
"/user/app/errors",
new Message(error.getMessage()));
}
}

三、客户端

STOMP 可以使用 stomp.js。接口参考: https://stomp-js.github.io/api-docs/latest/classes/Client.html

1、创建连接并订阅

let stomp = new StompJs.Client({
brokerURL: "ws://127.0.0.1:8080/demo?user=user01",
onConnect: function (frame) {
stomp.subscribe("/topic/marco", function (message) {
let obj = JSON.parse(message.body);
console.log("订阅的服务端消息:" + obj.message);
}); stomp.subscribe("/app/getShout", function (message) {
let obj = JSON.parse(message.body);
console.log("订阅的服务端应胜消息:" + obj.message);
}); stomp.subscribe("/user/app/errors", function (message) {
console.log("订阅的服务端返回的异常消息:" + message.body);
});
}
});

2、发送消息

stomp.publish({
destination: "/app/marco",
headers: {"content-type": "text/json"},
body: JSON.stringify({"message": "Marco!"})
});

Solon 之 STOMP的更多相关文章

  1. STOMP协议介绍

    STOMP,Streaming Text Orientated Message Protocol,是流文本定向消息协议,是一种为MOM(Message Oriented Middleware,面向消息 ...

  2. 浅谈压缩感知(二十五):压缩感知重构算法之分段正交匹配追踪(StOMP)

    主要内容: StOMP的算法流程 StOMP的MATLAB实现 一维信号的实验与结果 门限参数Ts.测量数M与重构成功概率关系的实验与结果 一.StOMP的算法流程 分段正交匹配追踪(Stagewis ...

  3. php 利用activeMq+stomp实现消息队列

    php 利用activeMq+stomp实现消息队列 一.activeMq概述 ActiveMQ 是Apache出品,最流行的,能力强劲的开源消息总线.ActiveMQ 是一个完全支持JMS1.1和J ...

  4. STOMP协议规范--转载

    原文地址:http://simlegate.com/2013/10/17/stomp-specification-1.2/ 摘要 STOMP是一个简单的可互操作的协议, 被用于通过中间服务器在客户端之 ...

  5. Apache.NMS.Stomp 下载

    最近项目中有用到ActiveMQ, MQ服务器61613的端口是用的STOMP协议, 原来项目中有使用MQ, 但发现缺少Apache.NMS.Stomp.dll的引用,于是上官网上找,结果发现所有的A ...

  6. 安装Stomp扩展时错误提示error: 'zend_class_entry' has no member named 'default_properties'

    在安装stomp扩展时, 有这样的提示 error: 'zend_class_entry' has no member named 'default_properties' 交待下安装上下文, sto ...

  7. ActiveMQ使用STOMP协议的一个错误问题:Unexpected ACK received for message-id

    使用某些语言环境下的stomp包(比如php python ruby),可能会出现如下问题: Unexpected ACK received for message-id 这一般可能有两个原因. 1. ...

  8. PHPWAMP开启php_stomp.dll的具体方式,php5.6开启stomp的图解过程

    友情提示:其他版本,方式一样的,大家依样画葫芦即可. 首先下载PHP 扩展php_stomp.dll文件,在php官方网站搜索"Stomp",搜索后,如下图 如下图点击" ...

  9. Spring 学习——基于Spring WebSocket 和STOMP实现简单的聊天功能

    本篇主要讲解如何使用Spring websocket 和STOMP搭建一个简单的聊天功能项目,里面使用到的技术,如websocket和STOMP等会简单介绍,不会太深,如果对相关介绍不是很了解的,请自 ...

  10. [转]压缩感知重构算法之分段正交匹配追踪(StOMP)

    分段正交匹配追踪(StagewiseOMP)或者翻译为逐步正交匹配追踪,它是OMP另一种改进算法,每次迭代可以选择多个原子.此算法的输入参数中没有信号稀疏度K,因此相比于ROMP及CoSaMP有独到的 ...

随机推荐

  1. pytorch的显存释放机制torch.cuda.empty_cache()

    参考: https://cloud.tencent.com/developer/article/1626387 据说在pytorch中使用torch.cuda.empty_cache()可以释放缓存空 ...

  2. 牛客周赛 Round 4

    牛客周赛 Round 4 A-游游的字符串构造_牛客周赛 Round 4 (nowcoder.com) 先把几个\('you'\)输出,剩下的随便输出 #pragma GCC optimize(3) ...

  3. LeetCode40.组合总和II

    LeetCode40.组合总和II 力扣题目链接(opens new window) 给定一个数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 ...

  4. kubernetes批量删除evicted状态pod

    #!/bin/bash # get namespace namespaces=`kubectl get pod -A | grep -i "evicted" | awk '{pri ...

  5. 模板链表类的扩展(QListEx<T>)

    以前写的链表都是比较简单的,插入节点是在头节点上,所以循环链表时都是从最后一个数据往前找的,给人的感觉是倒着的, 今天写一个在链表尾部插入数据 1.链表节点类的定义 /链表节点类 template & ...

  6. Tesla 开发者 API 指南:BLE 密钥 – 身份验证和车辆命令

    注意:本工具只能运行于 mac 或者 linux, win下不支持. 1. 克隆项目到本地 https://github.com/teslamotors/vehicle-command.git 2. ...

  7. Pandas从入门到放弃

    公众号本文地址:https://mp.weixin.qq.com/s/mSkA5KvL1390Js8_1ZBiyw Pandas简介 Pandas是Panel data(面板数据)和Data anal ...

  8. 总结篇3:redis 典型缓存架构设计问题及性能优化

    聊聊对于缓存预热.缓存穿透.缓存雪崩.缓存击穿.缓存更新.缓存降级的定义理解 缓存穿透 定义 当查询Redis中没有的数据时,该查询会下沉到数据库层,同时数据库层也没有该数据,当这种情况大量出现或被恶 ...

  9. EF Core – Get Started 搭建单侧环境

    有时候想搭个环境做测试, 又记不住那些 command, 官方教程又啰嗦. git clone 模板又不太好管理, 索性记入在这里吧. 创建项目 dotnet new webapp -o Simple ...

  10. MySQL 大表拆分

    概述 在实际工作中,在关系数据库(MySQL.PostgreSQL)的单表数据量上亿后,往往会出现查询和分析变慢甚至无法执行统计分析的情况.这时就需要将大表拆分为多个小表,将小表分布在多个数据库上,形 ...