当前位置: 首页 > news >正文

消息队列篇--通信协议篇--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&#xff08;Simple Text Oriented Messaging Protocol&#xff0c;简单面向文本的消息传递协议&#xff09;是一种轻量级、基于文本的协议&#xff0c;旨在为消息代理&#xff08;消息队列&#xff09;和客户端之间的通信&#xff08;websocket&#xff09;提供一种简单的…...

基于SpringBoot的租房管理系统(含论文)

基于SpringBoot的租房管理系统是一个集订单管理、房源信息管理、屋主申诉处理、用户反馈等多项功能于一体的系统。该系统通过SpringBoot框架开发&#xff0c;拥有完善的管理员后台、屋主管理模块、用户功能模块等&#xff0c;适用于房地产租赁平台或中介公司进行日常管理与运营…...

提升企业内部协作的在线知识库架构与实施策略

内容概要 在当前快速变化的商业环境中&#xff0c;企业对于提升内部协作效率的需求愈显迫切。在线知识库作为信息存储与共享的平台&#xff0c;成为了推动企业数字化转型的重要工具。本文将深入探讨如何有效打造与实施在线知识库&#xff0c;强调架构设计、知识资产分类管理及…...

【物联网】ARM核常用指令(详解):数据传送、计算、位运算、比较、跳转、内存访问、CPSR/SPSR、流水线及伪指令

文章目录 指令格式&#xff08;重点&#xff09;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开发中&#xff0c;Jackson库是处理JSON数据的常用工具。其中&#xff0c;JsonTypeId注解是一个非常实用的功能&#xff0c;它可以帮助我们更好地控制多态类型信息在序列化过程中的表现。今天&#xff0c;我们就来深入探讨一下JsonTypeId的用法&#xff0c;并通过具…...

Ubuntu 顶部状态栏 配置,gnu扩展程序

顶部状态栏 默认没有配置、隐藏的地方 安装使用Hide Top Bar 或Just Perfection等进行配置 1 安装 sudo apt install gnome-shell-extension-manager2 打开 安装的“扩展管理器” 3. 对顶部状态栏进行配置 使用Hide Top Bar 智能隐藏&#xff0c;或者使用Just Perfection 直…...

Java---入门基础篇(上)

前言 本片文章主要讲了刚学Java的一些基础内容,例如注释,标识符,数据类型和变量,运算符,还有逻辑控制等,记录的很详细,带你从简单的知识点再到练习题.如果学习了c语言的小伙伴会发现,这篇文章的内容和c语言大致相同. 而在下一篇文章里,我会讲解方法和数组的使用,也是Java中基础…...

Linux C++

一、引言 冯诺依曼架构是现代计算机系统的基础&#xff0c;它的提出为计算机的发展奠定了理论基础。在学习 C 和 Linux 系统时&#xff0c;理解冯诺依曼架构有助于我们更好地理解程序是如何在计算机中运行的&#xff0c;包括程序的存储、执行和资源管理。这对于编写高效、可靠的…...

gradio 合集

知识点 1&#xff1a;基本 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.论文链接&#xff1a;Bayesian, Systems-based, Multilevel Analysis of Associations for Complex Phenotypes: from Interpretation to Decision 摘要&#xff1a; 遗传关联研究&#xff08;GAS&#xff09;报告的结果相对稀缺&#xff0c;促使许多研究方向。尽管关联概念…...

代码随想录算法训练营第三十九天-动态规划-198. 打家劫舍

动规五部曲 dp[i]表示在下标为i的房间偷或不偷与前面所偷之和所能获得的最大价值递推公式&#xff1a;dp[i] std::max(dp[i - 2] nums[i], dp[i - 1])初始化&#xff1a;要给dp[0]与dp[1]来给定初始值&#xff0c;因为递推公式有-1与-2。dp[0] nums[0], dp[1] std::max(num…...

CF1098F Ж-function

【题意】 给你一个字符串 s s s&#xff0c;每次询问给你 l , r l, r l,r&#xff0c;让你输出 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−l1​LCP(ssi​,ss1​)。 【思路】 和前一道题一样&#…...

Python 函数魔法书:基础、范例、避坑、测验与项目实战

Python 函数魔法书&#xff1a;基础、范例、避坑、测验与项目实战 内容简介 本系列文章是为 Python3 学习者精心设计的一套全面、实用的学习指南&#xff0c;旨在帮助读者从基础入门到项目实战&#xff0c;全面提升编程能力。文章结构由 5 个版块组成&#xff0c;内容层层递进…...

vim交换文件的作用

1.数据恢复&#xff1a;因为vim异常的退出&#xff0c;使用交换文件可以恢复之前的修改内容。 2.防止多人同时编辑&#xff1a;vim检测到交换文件的存在,会给出提示&#xff0c;以避免一个文件同时被多人编辑。 &#xff08;vim交换文件的工作原理&#xff1a;vim交换文件的工作…...

[NOI1995] 石子合并

[NOI1995] 石子合并 题目描述 在一个圆形操场的四周摆放 N N N 堆石子&#xff0c;现要将石子有次序地合并成一堆&#xff0c;规定每次只能选相邻的 2 2 2 堆合并成新的一堆&#xff0c;并将新的一堆的石子数&#xff0c;记为该次合并的得分。 试设计出一个算法,计算出将 …...

真正的智能与那只蝴蝶

“蝴蝶效应”可以展开为对智能本质与大算力关系的追问&#xff0c;其中“蝴蝶”作为隐喻可能指向多重维度——从混沌理论的“蝴蝶效应”到庄子“物我两忘”的蝴蝶之梦。这种并置本身暗示了智能与宇宙秩序、认知边界之间的深刻张力。以下从三个层面展开分析&#xff1a;一、混沌…...

C++小病毒-1.0勒索(更新次数:2)

内容供学习使用,不得转卖,代码复制后请1小时内删除,此代码会危害计算机安全,谨慎操作 在C20环境下,并在虚拟机里运行此代码!&#xff0c;病毒带来后果自负! 使用时请删除在main()里的注释,并修改位置至C:\\(看我代码注释)//可以改成WIN Main() #include <iostream> #i…...

Node.js 的底层原理

Node.js 的底层原理 1. 事件驱动和非阻塞 I/O Node.js 基于 Chrome V8 引擎&#xff0c;使用 JavaScript 作为开发语言。它采用事件驱动和非阻塞 I/O 模型&#xff0c;使其轻量且高效。通过 libuv 库实现跨平台的异步 I/O&#xff0c;包括文件操作、网络请求等。 2. 单线程事…...

基于Django的豆瓣影视剧推荐系统的设计与实现

【Django】基于Django的豆瓣影视剧推荐系统的设计与实现&#xff08;完整系统源码开发笔记详细部署教程&#xff09;✅ 目录 一、项目简介二、项目界面展示三、项目视频展示 一、项目简介 该系统采用了Python作为后端开发语言&#xff0c;采用Django作为后端架构&#xff0c;结…...

Chapter03-Authentication vulnerabilities

文章目录 1. 身份验证简介1.1 What is authentication1.2 difference between authentication and authorization1.3 身份验证机制失效的原因1.4 身份验证机制失效的影响 2. 基于登录功能的漏洞2.1 密码爆破2.2 用户名枚举2.3 有缺陷的暴力破解防护2.3.1 如果用户登录尝试失败次…...

uniapp微信小程序视频实时流+pc端预览方案

方案类型技术实现是否免费优点缺点适用场景延迟范围开发复杂度​WebSocket图片帧​定时拍照Base64传输✅ 完全免费无需服务器 纯前端实现高延迟高流量 帧率极低个人demo测试 超低频监控500ms-2s⭐⭐​RTMP推流​TRTC/即构SDK推流❌ 付费方案 &#xff08;部分有免费额度&#x…...

前端开发面试题总结-JavaScript篇(一)

文章目录 JavaScript高频问答一、作用域与闭包1.什么是闭包&#xff08;Closure&#xff09;&#xff1f;闭包有什么应用场景和潜在问题&#xff1f;2.解释 JavaScript 的作用域链&#xff08;Scope Chain&#xff09; 二、原型与继承3.原型链是什么&#xff1f;如何实现继承&a…...

招商蛇口 | 执笔CID,启幕低密生活新境

作为中国城市生长的力量&#xff0c;招商蛇口以“美好生活承载者”为使命&#xff0c;深耕全球111座城市&#xff0c;以央企担当匠造时代理想人居。从深圳湾的开拓基因到西安高新CID的战略落子&#xff0c;招商蛇口始终与城市发展同频共振&#xff0c;以建筑诠释对土地与生活的…...

​​企业大模型服务合规指南:深度解析备案与登记制度​​

伴随AI技术的爆炸式发展&#xff0c;尤其是大模型&#xff08;LLM&#xff09;在各行各业的深度应用和整合&#xff0c;企业利用AI技术提升效率、创新服务的步伐不断加快。无论是像DeepSeek这样的前沿技术提供者&#xff0c;还是积极拥抱AI转型的传统企业&#xff0c;在面向公众…...

土建施工员考试:建筑施工技术重点知识有哪些?

《管理实务》是土建施工员考试中侧重实操应用与管理能力的科目&#xff0c;核心考查施工组织、质量安全、进度成本等现场管理要点。以下是结合考试大纲与高频考点整理的重点内容&#xff0c;附学习方向和应试技巧&#xff1a; 一、施工组织与进度管理 核心目标&#xff1a; 规…...

aardio 自动识别验证码输入

技术尝试 上周在发学习日志时有网友提议“在网页上识别验证码”&#xff0c;于是尝试整合图像识别与网页自动化技术&#xff0c;完成了这套模拟登录流程。核心思路是&#xff1a;截图验证码→OCR识别→自动填充表单→提交并验证结果。 代码在这里 import soImage; import we…...

信息系统分析与设计复习

2024试卷 单选题&#xff08;20&#xff09; 1、在一个聊天系统(类似ChatGPT)中&#xff0c;属于控制类的是&#xff08;&#xff09;。 A. 话语者类 B.聊天文字输入界面类 C. 聊天主题辨别类 D. 聊天历史类 ​解析 B-C-E备选架构中分析类分为边界类、控制类和实体类。 边界…...

HarmonyOS-ArkUI 自定义弹窗

自定义弹窗 自定义弹窗是界面开发中最为常用的一种弹窗写法。在自定义弹窗中&#xff0c; 布局样式完全由您决定&#xff0c;非常灵活。通常会被封装成工具类&#xff0c;以使得APP中所有弹窗具备相同的设计风格。 自定义弹窗具备的能力有 打开弹窗自定义布局&#xff0c;以…...

可视化图解算法48:有效括号序列

牛客网 面试笔试 TOP101 | LeetCode 20. 有效的括号 1. 题目 描述 给出一个仅包含字符(,),{,},[和],的字符串&#xff0c;判断给出的字符串是否是合法的括号序列 括号必须以正确的顺序关闭&#xff0c;"()"和"()[]{}"都是合法的括号序列&…...