消息队列篇--通信协议篇--STOMP(STOMP特点、格式及示例,WebSocket上使用STOMP,消息队列上使用STOMP等)
STOMP(Simple Text Oriented Messaging Protocol,简单面向文本的消息传递协议)是一种轻量级、基于文本的协议,旨在为消息代理(消息队列)和客户端之间的通信(websocket)提供一种简单的接口。它通常运行在TCP或WebSocket之上,并广泛用于实现发布/订阅、点对点消息传递等模式。
STOMP提供了一种简单的机制来发送和接收消息,适用于各种消息中间件系统,如ActiveMQ、RabbitMQ和Apache Kafka等。
特点:
- 基于文本的协议,简单易用,适合快速开发。
- 支持多种消息传递模式(如发布/订阅、点对点)。
- 支持事务和消息确认机制。
- 轻量级,适用于资源受限的环境(宽带低等)。
- 支持多种消息代理(如RabbitMQ、ActiveMQ)。
- 支持客户端之间的通信(如:websocket)
适用场景:
- 实时通信应用(如聊天系统、社交网络)。
- 微服务之间的异步通信。
- IoT设备之间的轻量级通信。
1、STOMP基本概念
(1)、目的地(Destination)
目的地是消息发送或接收的目标地址。
常见的目的地类型包括:
- 队列(Queue):点对点消息传递模式,每条消息只会被一个消费者处理。
- 主题(Topic):发布/订阅模式,每条消息会被所有订阅者处理。
(2)、命令(Commands)
STOMP定义了若干命令,用于控制消息的发送、接收和管理。
常见的命令包括:
- CONNECT:建立连接。
- SEND:发送消息到指定的目的地。
- SUBSCRIBE:订阅某个目的地,接收该目的地的消息。
- UNSUBSCRIBE:取消订阅某个目的地。
- ACK:确认消息已被成功处理。
- NACK:拒绝或无法处理消息。
- DISCONNECT:断开连接。
(3)、头信息(Headers)
头信息是伴随每个命令的键值对,用于传递额外的元数据。
常见的头信息包括:
- destination:消息的目的地。
- id:订阅的唯一标识符。
- receipt:请求服务器返回一个收据,确认命令已执行。
(4)、消息体(Body)
消息体包含实际的消息内容,可以是任意格式的数据(如JSON、XML、纯文本等)。消息体必须以空字节\u0000结束。
2、STOMP消息格式
每条STOMP消息由命令行、头信息和消息体组成,各部分之间用换行符\n分隔,整个消息以两个连续的换行符\n\n结束。
示例:CONNECT命令
CONNECT
accept-version:1.2
host:stomp.example.com^@
解释:
- CONNECT:命令名称。
- accept-version:1.2:表示支持的STOMP版本。
- host:stomp.example.com:目标主机。
- ^@:表示消息体为空,用一个空字节(ASCII码为0)来表示。
示例:SEND命令
SEND
destination:/queue/workHello, STOMP!
^@
解释:
- SEND:命令名称。
- destination:/queue/work:消息的目的地。
- Hello, STOMP!:消息的内容。
- ^@:表示消息结束。
示例:SUBSCRIBE命令
SUBSCRIBE
id:sub-001
destination:/topic/greetings^@
解释:
- SUBSCRIBE:命令名称。
- id:sub-001:订阅的唯一标识符。
- destination:/topic/greetings:要订阅的主题地址。
- ^@:表示消息体为空。
3、STOMP工作流程
原理示意图:

(1)、连接
客户端首先需要通过CONNECT命令与STOMP服务器建立连接。如果连接成功,服务器会返回一个CONNECTED响应。
客户端示例:
CONNECT
accept-version:1.2
host:stomp.example.com^@
服务器响应示例:
CONNECTED
version:1.2
session:session-id-12345^@
(2)、订阅
客户端可以通过SUBSCRIBE命令订阅某个目的地,接收该目的地的消息。
客户端示例:
SUBSCRIBE
id:sub-001
destination:/topic/greetings^@
(3)、发送消息
客户端可以通过SEND命令向某个目的地发送消息。
客户端示例:
SEND
destination:/queue/workHello, STOMP!
^@
(4)、接收消息
当有消息到达客户端订阅的目的地时,服务器会将消息推送到客户端。
消息示例:
MESSAGE
subscription:sub-001
message-id:message-id-67890
destination:/topic/greetingsHello, World!
^@
(5)、断开连接
客户端可以通过DISCONNECT命令断开与服务器的连接。
客户端示例:
DISCONNECT^@
4、在WebSocket上使用STOMP
在WebSocket之上使用STOMP时,STOMP消息作为WebSocket数据帧的有效载荷进行传输。这种方式结合了WebSocket的全双工通信能力和STOMP的结构化消息传递功能。
示例:JavaScript中使用WebSocket和STOMP
const socket = new WebSocket('ws://example.com/stomp-endpoint'); // 建立websocket连接socket.onopen = function() {// 发送CONNECT命令const connectMessage = CONNECT\naccept-version:1.2\nhost:example.com\n\n\u0000;socket.send(connectMessage);// 发送SUBSCRIBE命令const subscribeMessage = SUBSCRIBE\nid:sub-001\ndestination:/topic/greetings\n\n\u0000;socket.send(subscribeMessage);
};socket.onmessage = function(event) {console.log('Received:', event.data);// 解析收到的STOMP消息if (event.data.startsWith('MESSAGE')) {console.log('New message:', event.data.split('\n\n')[1].trim());}
};
5、代码示例
依赖库:
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-messaging</artifactId>
</dependency>
发送消息:
import org.springframework.messaging.converter.MappingJackson2MessageConverter;
import org.springframework.messaging.simp.stomp.StompFrameHandler;
import org.springframework.messaging.simp.stomp.StompHeaders;
import org.springframework.messaging.simp.stomp.StompSession;
import org.springframework.messaging.simp.stomp.StompSessionHandlerAdapter;
import org.springframework.web.socket.client.standard.StandardWebSocketClient;
import org.springframework.web.socket.messaging.WebSocketStompClient;
import org.springframework.web.socket.sockjs.client.SockJsClient;
import org.springframework.web.socket.sockjs.client.Transport;
import org.springframework.web.socket.sockjs.client.WebSocketTransport;
import java.lang.reflect.Type;
import java.util.Collections;
import java.util.concurrent.ExecutionException;public class StompProducer {public static void main(String[] args) throws ExecutionException, InterruptedException {// 创建 WebSocket 客户端StandardWebSocketClient wsClient = new StandardWebSocketClient();SockJsClient sockJsClient = new SockJsClient(Collections.singletonList(new WebSocketTransport(wsClient)));// 创建STOMP客户端WebSocketStompClient stompClient = new WebSocketStompClient(sockJsClient);stompClient.setMessageConverter(new MappingJackson2MessageConverter());// 连接到STOMP代理StompSession session = stompClient.connect("ws://localhost:8080/ws", new StompSessionHandlerAdapter() {}).get();// 发送消息StompHeaders headers = new StompHeaders();headers.setDestination("/app/hello");session.send(headers, "Hello, STOMP!");System.out.println("Message sent");}
}
接收消息:
import org.springframework.messaging.converter.MappingJackson2MessageConverter;
import org.springframework.messaging.simp.stomp.StompFrameHandler;
import org.springframework.messaging.simp.stomp.StompHeaders;
import org.springframework.messaging.simp.stomp.StompSession;
import org.springframework.messaging.simp.stomp.StompSessionHandlerAdapter;
import org.springframework.web.socket.client.standard.StandardWebSocketClient;
import org.springframework.web.socket.messaging.WebSocketStompClient;
import org.springframework.web.socket.sockjs.client.SockJsClient;
import org.springframework.web.socket.sockjs.client.Transport;
import org.springframework.web.socket.sockjs.client.WebSocketTransport;
import java.lang.reflect.Type;
import java.util.Collections;
import java.util.concurrent.ExecutionException;public class StompConsumer {public static void main(String[] args) throws ExecutionException, InterruptedException {// 创建WebSocket客户端StandardWebSocketClient wsClient = new StandardWebSocketClient();SockJsClient sockJsClient = new SockJsClient(Collections.singletonList(new WebSocketTransport(wsClient)));// 创建STOMP客户端WebSocketStompClient stompClient = new WebSocketStompClient(sockJsClient);stompClient.setMessageConverter(new MappingJackson2MessageConverter());// 连接到STOMP代理StompSession session = stompClient.connect("ws://localhost:8080/ws", new StompSessionHandlerAdapter() {}).get();// 订阅主题并设置回调session.subscribe("/topic/greetings", new StompFrameHandler() {@Overridepublic Type getPayloadType(StompHeaders headers) {return String.class;}@Overridepublic void handleFrame(StompHeaders headers, Object payload) {System.out.println("Received message: " + payload);}});// 保持连接Thread.sleep(Long.MAX_VALUE);}
}
6、总结
STOMP是一种简单而强大的消息传递协议,特别适合于需要灵活消息路由的应用场景。通过运行在WebSocket或其他传输协议之上。
STOMP提供了以下优势:
- 易用性:基于文本的协议,易于实现和调试。
- 灵活性:支持多种消息传递模式,适应不同的应用场景。
- 跨平台:可以在多种编程语言和平台上使用,具有良好的互操作性。
通过理解STOMP的基本概念、命令和工作流程,开发者可以有效地利用这一协议构建高效的消息传递系统。
乘风破浪!Dare to Be!!!
相关文章:
消息队列篇--通信协议篇--STOMP(STOMP特点、格式及示例,WebSocket上使用STOMP,消息队列上使用STOMP等)
STOMP(Simple Text Oriented Messaging Protocol,简单面向文本的消息传递协议)是一种轻量级、基于文本的协议,旨在为消息代理(消息队列)和客户端之间的通信(websocket)提供一种简单的…...
基于SpringBoot的租房管理系统(含论文)
基于SpringBoot的租房管理系统是一个集订单管理、房源信息管理、屋主申诉处理、用户反馈等多项功能于一体的系统。该系统通过SpringBoot框架开发,拥有完善的管理员后台、屋主管理模块、用户功能模块等,适用于房地产租赁平台或中介公司进行日常管理与运营…...
提升企业内部协作的在线知识库架构与实施策略
内容概要 在当前快速变化的商业环境中,企业对于提升内部协作效率的需求愈显迫切。在线知识库作为信息存储与共享的平台,成为了推动企业数字化转型的重要工具。本文将深入探讨如何有效打造与实施在线知识库,强调架构设计、知识资产分类管理及…...
【物联网】ARM核常用指令(详解):数据传送、计算、位运算、比较、跳转、内存访问、CPSR/SPSR、流水线及伪指令
文章目录 指令格式(重点)1. 立即数2. 寄存器位移 一、数据传送指令1. MOV指令2. MVN指令3. LDR指令 二、数据计算指令1. ADD指令1. SUB指令1. MUL指令 三、位运算指令1. AND指令2. ORR指令3. EOR指令4. BIC指令 四、比较指令五、跳转指令1. B/BL指令2. l…...
Jackson中@JsonTypeId的妙用与实例解析
在日常的Java开发中,Jackson库是处理JSON数据的常用工具。其中,JsonTypeId注解是一个非常实用的功能,它可以帮助我们更好地控制多态类型信息在序列化过程中的表现。今天,我们就来深入探讨一下JsonTypeId的用法,并通过具…...
Ubuntu 顶部状态栏 配置,gnu扩展程序
顶部状态栏 默认没有配置、隐藏的地方 安装使用Hide Top Bar 或Just Perfection等进行配置 1 安装 sudo apt install gnome-shell-extension-manager2 打开 安装的“扩展管理器” 3. 对顶部状态栏进行配置 使用Hide Top Bar 智能隐藏,或者使用Just Perfection 直…...
Java---入门基础篇(上)
前言 本片文章主要讲了刚学Java的一些基础内容,例如注释,标识符,数据类型和变量,运算符,还有逻辑控制等,记录的很详细,带你从简单的知识点再到练习题.如果学习了c语言的小伙伴会发现,这篇文章的内容和c语言大致相同. 而在下一篇文章里,我会讲解方法和数组的使用,也是Java中基础…...
Linux C++
一、引言 冯诺依曼架构是现代计算机系统的基础,它的提出为计算机的发展奠定了理论基础。在学习 C 和 Linux 系统时,理解冯诺依曼架构有助于我们更好地理解程序是如何在计算机中运行的,包括程序的存储、执行和资源管理。这对于编写高效、可靠的…...
gradio 合集
知识点 1:基本 Chatbot 创建 import gradio as gr 定义历史记录 history [gr.ChatMessage(role“assistant”, content“How can I help you?”), gr.ChatMessage(role“user”, content“What is the weather today?”)] 使用历史记录创建 Chatbot 组件 ch…...
996引擎 - NPC-动态创建NPC
996引擎 - NPC-动态创建NPC 创建脚本服务端脚本客户端脚本添加自定义音效添加音效文件修改配置参考资料有个小问题,创建NPC时没有控制朝向的参数。所以。。。自己考虑怎么找补吧。 多重影分身 创建脚本 服务端脚本 Mir200\Envir\Market_Def\test\test001-3.lua -- NPC八门名…...
论文阅读(十三):复杂表型关联的贝叶斯、基于系统的多层次分析:从解释到决策
1.论文链接:Bayesian, Systems-based, Multilevel Analysis of Associations for Complex Phenotypes: from Interpretation to Decision 摘要: 遗传关联研究(GAS)报告的结果相对稀缺,促使许多研究方向。尽管关联概念…...
代码随想录算法训练营第三十九天-动态规划-198. 打家劫舍
动规五部曲 dp[i]表示在下标为i的房间偷或不偷与前面所偷之和所能获得的最大价值递推公式:dp[i] std::max(dp[i - 2] nums[i], dp[i - 1])初始化:要给dp[0]与dp[1]来给定初始值,因为递推公式有-1与-2。dp[0] nums[0], dp[1] std::max(num…...
CF1098F Ж-function
【题意】 给你一个字符串 s s s,每次询问给你 l , r l, r l,r,让你输出 s s s l , r sss_{l,r} sssl,r中 ∑ i 1 r − l 1 L C P ( s s i , s s 1 ) \sum_{i1}^{r-l1}LCP(ss_i,ss_1) ∑i1r−l1LCP(ssi,ss1)。 【思路】 和前一道题一样&#…...
Python 函数魔法书:基础、范例、避坑、测验与项目实战
Python 函数魔法书:基础、范例、避坑、测验与项目实战 内容简介 本系列文章是为 Python3 学习者精心设计的一套全面、实用的学习指南,旨在帮助读者从基础入门到项目实战,全面提升编程能力。文章结构由 5 个版块组成,内容层层递进…...
vim交换文件的作用
1.数据恢复:因为vim异常的退出,使用交换文件可以恢复之前的修改内容。 2.防止多人同时编辑:vim检测到交换文件的存在,会给出提示,以避免一个文件同时被多人编辑。 (vim交换文件的工作原理:vim交换文件的工作…...
[NOI1995] 石子合并
[NOI1995] 石子合并 题目描述 在一个圆形操场的四周摆放 N N N 堆石子,现要将石子有次序地合并成一堆,规定每次只能选相邻的 2 2 2 堆合并成新的一堆,并将新的一堆的石子数,记为该次合并的得分。 试设计出一个算法,计算出将 …...
真正的智能与那只蝴蝶
“蝴蝶效应”可以展开为对智能本质与大算力关系的追问,其中“蝴蝶”作为隐喻可能指向多重维度——从混沌理论的“蝴蝶效应”到庄子“物我两忘”的蝴蝶之梦。这种并置本身暗示了智能与宇宙秩序、认知边界之间的深刻张力。以下从三个层面展开分析:一、混沌…...
C++小病毒-1.0勒索(更新次数:2)
内容供学习使用,不得转卖,代码复制后请1小时内删除,此代码会危害计算机安全,谨慎操作 在C20环境下,并在虚拟机里运行此代码!,病毒带来后果自负! 使用时请删除在main()里的注释,并修改位置至C:\\(看我代码注释)//可以改成WIN Main() #include <iostream> #i…...
Node.js 的底层原理
Node.js 的底层原理 1. 事件驱动和非阻塞 I/O Node.js 基于 Chrome V8 引擎,使用 JavaScript 作为开发语言。它采用事件驱动和非阻塞 I/O 模型,使其轻量且高效。通过 libuv 库实现跨平台的异步 I/O,包括文件操作、网络请求等。 2. 单线程事…...
基于Django的豆瓣影视剧推荐系统的设计与实现
【Django】基于Django的豆瓣影视剧推荐系统的设计与实现(完整系统源码开发笔记详细部署教程)✅ 目录 一、项目简介二、项目界面展示三、项目视频展示 一、项目简介 该系统采用了Python作为后端开发语言,采用Django作为后端架构,结…...
硬件相关项目内容介绍(硬件咱们也有相关技术支持内容哦)
硬件相关项目内容介绍(硬件咱们也有相关技术支持内容哦) 硬件咱们也有相关技术支持内容哦。 主要看大家喜欢什么,硬件内容咱们会不定期更新分享,大家要是喜欢,后续就安排上实物实操。也虚心听取大家建议,不…...
微软创新者窘境:从J的离开看大公司如何留住颠覆性人才
1. 从“J”的离去看微软的“创新者窘境”2010年5月,当微软宣布其娱乐与设备事业部(E&D)的重组,以及J Allard和Robbie Bach两位核心人物的离开时,科技圈的反应是复杂的。表面上看,这是一次常规的高层人事…...
VisualCppRedist AIO:一站式解决Windows应用程序运行库缺失难题
VisualCppRedist AIO:一站式解决Windows应用程序运行库缺失难题 【免费下载链接】vcredist AIO Repack for latest Microsoft Visual C Redistributable Runtimes 项目地址: https://gitcode.com/gh_mirrors/vc/vcredist 在Windows系统中,你是否经…...
Encounter/Innovus GIFT TCL 脚本流程索引清单
目录 一、 布局阶段 (Placement) 二、 布线阶段 (Routing) 三、 时序阶段 (Timing) 四、 电源阶段 (Power) 五、 IO 与端口处理 六、 调试与辅助工具 一、 布局阶段 (Placement) 脚本名称 核心用途 调用场景 userAddAllHInsts.tcl 为源模块中的每个扇出添加缓冲器 解决高扇…...
Midjourney v7新功能全维度压测报告(v6 vs v7实测对比:提示词容错率↑47%,构图理解准确率突破92.6%)
更多请点击: https://intelliparadigm.com 第一章:Midjourney v7新功能全面解析 Midjourney v7 于2024年第三季度正式发布,标志着AI图像生成在语义理解、构图控制与跨模态一致性方面迈入新阶段。本次升级不再仅依赖提示词(prompt…...
全网没人敢说,关于中小企业AI营销一体机到底是卖硬件还是卖落地闭环的屎盆子,我先扣为敬。
[实话] 干这行十年,我拍着桌子定过一条死规矩。三个不做:不做只卖盒子不管结果的,不做签完合同就消失的,不做让你自己研究三个月才能用的。[实话] 现在的“AI营销一体机”,90%都是在收智商税。我见过太多老板ÿ…...
本地AI任务编排工具AgentForge:从看板管理到多代理协作
1. 项目概述:一个能调度AI编码代理的本地看板工具如果你和我一样,日常开发中经常需要让Claude Code这类AI编码助手去执行一些重复性的代码审查、重构或者生成任务,并且希望这些任务能像CI/CD流水线一样被编排、调度和监控,那么你一…...
航拍UAV电力电缆巡检检测数据集_数据集第10027期
航拍UAV电力电缆巡检检测数据集_数据集第10027期 项目简介 面向无人机电力巡检场景的开源目标检测数据集,聚焦电力电缆识别任务,可用于电力线检测、植被与电力线安全距离监测等场景,助力电力巡检智能化。 数据集核心信息 数据规模:…...
Windows平台ADB驱动终极安装指南:3分钟搞定Android开发环境
Windows平台ADB驱动终极安装指南:3分钟搞定Android开发环境 【免费下载链接】Latest-adb-fastboot-installer-for-windows A Simple Android Driver installer tool for windows (Always installs the latest version) 项目地址: https://gitcode.com/gh_mirrors/…...
DavyBot开源框架:构建智能对话机器人的模块化实践指南
1. 项目概述:一个开箱即用的智能对话机器人框架最近在折腾聊天机器人项目,发现了一个挺有意思的开源项目,叫geluzhiwei1/davybot。乍一看这个名字,可能觉得有点陌生,但如果你在GitHub上搜索过聊天机器人、智能客服或者…...
