Solon 之 STOMP
一、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/");}@Overridepublic 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
一、STOMP 简介 如果直接使用 WebSocket 会非常累,就像用 Socket 编写 Web 应用。没有高层级的交互协议,就需要我们定义应用间所发消息的语义,还需要确保连接的两端都能遵循这些语义。 如 HTTP 在 TCP 套接字之上添加了请求-响应模型层一样…...
在掌控板上搭建http服务器
在掌控板上搭建http服务器 打开Arduino IDE,并且已经添加了ESP32的支持库。以下是创建一个基本HTTP服务器的步骤: 包含必要的库: #include <WiFi.h> #include <WebServer.h>配置WiFi: 替换ssid和password为你的WiFi网…...
HCIA复习实验
实验要求 实验拓扑以及实验分析 第一步先划分网段 先对内网划分 192.168.1.0/24划分 192.168.1.0/26---骨干主线路 192.168.1.64/26---骨干备线路 ---192.168.1.128/25--vlan2 3汇总---便于减少路由表条目---在大型网络方便 192.168.1.128/26---vlan2 192.168.1.192/26---vla…...
生信软件39 - GATK最佳实践流程重构,提高17倍分析速度的LUSH流程
1. LUSH流程简介 基因组测序通常用于分子诊断、分期和预后,而大量测序数据在分析时间方面提出了挑战。 对于从FASTQ到VCF的整个流程,LUSH流程在非GVCF和GVCF模式下都大大降低了运行时间,30 X WGS数据耗时不到2 h,从BAM到VCF约需…...
c#编写的各类应用程序、类库的引用(黑白盒)
001 课程简介,C# 语言简介,开发环境准备 (yuque.com)https://www.yuque.com/yuejiangliu/dotnet/timothy-csharp-001 一个Solution里包含多个Project 一、见识 C# 编写的各类应用程序 二、类库的引用(黑/白盒引用) 1、黑盒引用&a…...
计算机网络考研笔记
...
用感性的方式浅要了解什么是AI 与 大模型
什么是人工智能(AI)? 人工智能(Artificial Intelligence,简称 AI)是指由人制造出来的具有一定智能的系统,能够理解和学习人类的行为,并在某些任务上模仿人类的智能行为。这些任务包…...
Linux文件的查找和打包以及压缩
文件的查找 文件查找的用处,在我们需要文件但却又不知道文件在哪里的时候 文件查找存在着三种类型的查找 1、which或whereis:查找命令的程序文件位置 2、locate:也是一种文件查找,但是基于数据库的查找 3、find:针…...
专题十四_哈希表_算法专题详细解答
目录 哈希表简介 1. 两数之和(easy) 解析: 解法一:暴力: 解法二:哈希O(N) 总结: 2. 判断是否互为字符重排(easy) 解析: 哈希: 总结&…...
C++源码生成·序章
文章目录 C源码生成序章1 概述1.1 前言1.2 Python 易用性简介 2 使用 python 生成 c 源码2.1 运行脚本2.2 结果 3 项目启动3.1 项目概述3.2 环境准备3.3 克隆仓库3.4 查看标签(Tags)3.4 根据标签拉取代码3.5 后续步骤 C源码生成序章 1 概述 1.1 前言 …...
Android中的MVP模式
MVP(Model-View-Presenter)架构在 Android 开发中是一种流行的架构模式,它将业务逻辑和 UI 代码分离,通过 Presenter 来处理用户的操作和界面更新。MVP 提高了代码的可维护性和测试性,特别是 Presenter 中的逻辑可以单…...
kebuadm部署k8s集群
官方文档: Installing kubeadm | Kubernetes 切记要关闭防⽕墙、selinux、禁用交换空间, cpu核⼼数⾄少为2 内存4G kubeadm部署k8s⾼可用集群的官方文档: Creating Highly Available Clusters with kubeadm | Kubernetes 你需要在每台…...
Unity3D学习FPS游戏(2)简单场景、玩家移动控制
前言:上一篇的时候,我们已经导入了官方fps的素材,并且对三维模型有了一定了解。接下来我们要构建一个简单的场景让玩家能够有地方移动,然后写一个简单的玩家移动控制。 简单场景和玩家移动 简单场景玩家移动控制玩家模型视野-摄像…...
网上的 AQS 文章让我很失望
一、AQS 很多人都没有讲明白 🤔 翻看了网上的 AQS(AbstractQueuedSynchronizer)文章,质量参差不齐,大多数都是在关键处跳过、含糊其词,美其名曰 “传播知识” 。 大多数都是进行大段的源码粘贴和注释&…...
滑动窗口子串
文章目录 滑动窗口一、无重复字符的最长子串二、找到字符串中所有字母异位词 子串三、和为 K 的子数组四、滑动窗口最大值五、最小覆盖子串 滑动窗口 一、无重复字符的最长子串 题目链接 (方法一:暴力枚举) (方法二ÿ…...
【windows11 提示“Microsoft Visual C++ Runtime Library Runtime Error】
windows11 提示“Microsoft Visual C++ Runtime Library Runtime Error” 问题描述解决方法郑重声明:本人原创博文,都是实战,均经过实际项目验证出货的 转载请标明出处:攻城狮2015 Platform: windows OS:windows11 问题描述 解决方法 下载VisualCppRedist_AIO_x86_x64.exe 安…...
【leetcode|哈希表、动态规划】最长连续序列、最大子数组和
目录 最长连续序列 解法一:暴力枚举 复杂度 解法二:优化解法一省去二层循环中不必要的遍历 复杂度 最大子数组和 解法一:暴力枚举 复杂度 解法二:贪心 复杂度 解法三:动态规划 复杂度 最长连续序列 输入输…...
【人工智能】掌握深度学习中的时间序列预测:深入解析RNN与LSTM的工作原理与应用
深度学习中的循环神经网络(RNN)和长短时记忆网络(LSTM)在处理时间序列数据方面具有重要作用。它们能够通过记忆前序信息,捕捉序列数据中的长期依赖性,广泛应用于金融市场预测、自然语言处理、语音识别等领域…...
今日开放!24下软考机考「模拟练习平台」操作指南来啦!
2024年下半年软考机考模拟练习平台今日开放,考生可以下载模拟作答系统并登录后进行模拟练习,熟悉答题流程及操作方法。 一、模拟练习时间 2024年下半年软考机考模拟练习平台开放时间为2024年10月23日9:00至11月6日17:00,共15天。 考生可以在…...
合并.md文档
需求:将多个.md文档合并成一个.md文档。 方法一:通过 type 命令 参考内容:多个md文件合并 步骤: 把需要合并的 .md 文档放入到一个文件夹内。修改需要合并的 .md 文档名,可以在文档名前加上 1.2.3 来表明顺序&#x…...
大数据学习栈记——Neo4j的安装与使用
本文介绍图数据库Neofj的安装与使用,操作系统:Ubuntu24.04,Neofj版本:2025.04.0。 Apt安装 Neofj可以进行官网安装:Neo4j Deployment Center - Graph Database & Analytics 我这里安装是添加软件源的方法 最新版…...
【位运算】消失的两个数字(hard)
消失的两个数字(hard) 题⽬描述:解法(位运算):Java 算法代码:更简便代码 题⽬链接:⾯试题 17.19. 消失的两个数字 题⽬描述: 给定⼀个数组,包含从 1 到 N 所有…...
UE5 学习系列(三)创建和移动物体
这篇博客是该系列的第三篇,是在之前两篇博客的基础上展开,主要介绍如何在操作界面中创建和拖动物体,这篇博客跟随的视频链接如下: B 站视频:s03-创建和移动物体 如果你不打算开之前的博客并且对UE5 比较熟的话按照以…...
dedecms 织梦自定义表单留言增加ajax验证码功能
增加ajax功能模块,用户不点击提交按钮,只要输入框失去焦点,就会提前提示验证码是否正确。 一,模板上增加验证码 <input name"vdcode"id"vdcode" placeholder"请输入验证码" type"text&quo…...
MMaDA: Multimodal Large Diffusion Language Models
CODE : https://github.com/Gen-Verse/MMaDA Abstract 我们介绍了一种新型的多模态扩散基础模型MMaDA,它被设计用于在文本推理、多模态理解和文本到图像生成等不同领域实现卓越的性能。该方法的特点是三个关键创新:(i) MMaDA采用统一的扩散架构…...
el-switch文字内置
el-switch文字内置 效果 vue <div style"color:#ffffff;font-size:14px;float:left;margin-bottom:5px;margin-right:5px;">自动加载</div> <el-switch v-model"value" active-color"#3E99FB" inactive-color"#DCDFE6"…...
1.3 VSCode安装与环境配置
进入网址Visual Studio Code - Code Editing. Redefined下载.deb文件,然后打开终端,进入下载文件夹,键入命令 sudo dpkg -i code_1.100.3-1748872405_amd64.deb 在终端键入命令code即启动vscode 需要安装插件列表 1.Chinese简化 2.ros …...
屋顶变身“发电站” ,中天合创屋面分布式光伏发电项目顺利并网!
5月28日,中天合创屋面分布式光伏发电项目顺利并网发电,该项目位于内蒙古自治区鄂尔多斯市乌审旗,项目利用中天合创聚乙烯、聚丙烯仓库屋面作为场地建设光伏电站,总装机容量为9.96MWp。 项目投运后,每年可节约标煤3670…...
python如何将word的doc另存为docx
将 DOCX 文件另存为 DOCX 格式(Python 实现) 在 Python 中,你可以使用 python-docx 库来操作 Word 文档。不过需要注意的是,.doc 是旧的 Word 格式,而 .docx 是新的基于 XML 的格式。python-docx 只能处理 .docx 格式…...
【 java 虚拟机知识 第一篇 】
目录 1.内存模型 1.1.JVM内存模型的介绍 1.2.堆和栈的区别 1.3.栈的存储细节 1.4.堆的部分 1.5.程序计数器的作用 1.6.方法区的内容 1.7.字符串池 1.8.引用类型 1.9.内存泄漏与内存溢出 1.10.会出现内存溢出的结构 1.内存模型 1.1.JVM内存模型的介绍 内存模型主要分…...
