消息队列篇--通信协议篇--STOMP(STOMP特点、格式及示例,WebSocket上使用STOMP,消息队列上使用STOMP等)

news/2025/2/1 20:09:09/

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!!!


http://www.ppmy.cn/news/1568504.html

相关文章

Clock Controller of RH850/F1KH-D8, RH850/F1KM-S4, RH850/F1KM-S2

&esmp; 时钟控制器由时钟振荡电路、时钟选择电路、和时钟输出电路组成。   RH850/F1KH、RH850/F1KM单片机的时钟控制器具有以下特点: 六个片上时钟振荡器: 主振荡器(MainOSC),振荡频率分别为8、16、20和24 MHz子振荡器(SubOSC),振荡频率为32.768 kHz*1 100针的产品…

【浏览器 - Mac实时调试iOS手机浏览器页面】

最近开发个项目&#xff0c;需要在 Mac 电脑上调试 iOS 手机设备上的 Chrome 浏览器&#xff0c;并查看Chrome网页上的 console 信息&#xff0c;本来以为要安装一些插件&#xff0c;没想到直接使用Mac上的Safari 直接可以调试&#xff0c;再此记录下&#xff0c;分享给需要的伙…

基础项目实战——3D赛车(c++)

目录 前言一、渲染引擎二、关闭事件三、梯形绘制四、轨道绘制五、边缘绘制六、草坪绘制七、前后移动八、左右移动​九、曲线轨道​十、课山坡轨道​十一、循环轨道​十二、背景展示​十三、引入速度​十四、物品绘制​十五、课数字路障​十六、分数展示​十七、重新生成​十八、…

物联网智能项目之——智能家居项目的实现!

成长路上不孤单&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a; 【14后&#x1f60a;///计算机爱好者&#x1f60a;///持续分享所学&#x1f60a;///如有需要欢迎收藏转发///&#x1f60a;】 今日分享关于物联网智能项目之——智能家居项目…

青少年编程与数学 02-008 Pyhon语言编程基础 08课题、变量与赋值

青少年编程与数学 02-008 Pyhon语言编程基础 08课题、变量与赋值 一、变量1. 动态类型2. 命名规则3. 赋值4. 可变性5. 引用6. 作用域7. 垃圾回收 二、定义和使用变量1. 定义变量2. 变量命名规则3. 使用变量4. 变量的动态类型5. 多个变量赋值6. 序列解包7. 变量作用域8. 变量的可…

机器学习6-全连接神经网络2

机器学习6-全连接神经网络2-梯度算法改进 梯度下降算法存在的问题动量法与自适应梯度动量法一、动量法的核心思想二、动量法的数学表示三、动量法的作用四、动量法的应用五、示例 自适应梯度与RMSProp 权值初始化随机权值初始化Xavier初始化HE初始化(MSRA) ![在这里插入图片描述…

Three.js 中实现自定义光圈 Shader 效果

目录 前言 Three.js 与自定义着色器的基础知识 效果展示代码概览 顶点着色器的作用 Uniforms 的作用 动画实现 前言 Three.js 是一个功能强大的 WebGL 库&#xff0c;它让开发者能够轻松地创建复杂的 3D 场景、动画和交互效果。然而&#xff0c;有时候内置的材质和效果无…

图漾相机——C++语言属性设置

文章目录 前言1.SDK API功能介绍1.1 Device组件下的API测试1.1.1 相机工作模式设置&#xff08;TY_TRIGGER_PARAM_EX&#xff09;1.1.2 TY_INT_FRAME_PER_TRIGGER1.1.3 TY_INT_PACKET_DELAY1.1.4 TY_INT_PACKET_SIZE1.1.5 TY_BOOL_GVSP_RESEND1.1.6 TY_BOOL_TRIGGER_OUT_IO1.1.…