在Spring Boot项目中集成和使用MQTT
在物联网(IoT)应用中,MQTT(消息队列遥测传输)协议因其轻量级和高效性被广泛使用。在Spring Boot项目中,我们可以通过集成org.springframework.integration:spring-integration-mqtt依赖来实现对MQTT的支持。本文将逐步介绍如何在Spring Boot应用中使用MQTT。
1. 添加依赖
首先,我们需要在项目的pom.xml文件中添加Spring Integration MQTT的依赖:
<dependencies><!-- Spring Boot Starter --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency><!-- Spring Integration MQTT --><dependency><groupId>org.springframework.integration</groupId><artifactId>spring-integration-mqtt</artifactId></dependency><!-- MQTT Client Library (Paho) --><dependency><groupId>org.eclipse.paho</groupId><artifactId>org.eclipse.paho.client.mqttv3</artifactId></dependency>
</dependencies>
2. 配置MQTT
在Spring Boot应用的配置文件application.properties中添加MQTT相关配置:
mqtt.broker.url=tcp://localhost:1883
mqtt.client.id=spring-boot-mqtt-client
mqtt.username=your-username
mqtt.password=your-password
mqtt.default.topic=your/topic
3. 创建MQTT配置类
创建一个新的配置类,用于配置MQTT连接和消息处理:
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.integration.annotation.ServiceActivator;
import org.springframework.integration.channel.DirectChannel;
import org.springframework.integration.core.MessageProducer;
import org.springframework.integration.mqtt.core.DefaultMqttPahoClientFactory;
import org.springframework.integration.mqtt.core.MqttPahoClientFactory;
import org.springframework.integration.mqtt.inbound.MqttPahoMessageDrivenChannelAdapter;
import org.springframework.integration.mqtt.outbound.MqttPahoMessageHandler;
import org.springframework.integration.mqtt.support.DefaultPahoMessageConverter;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.MessageHandler;@Configuration
public class MqttConfig {@Beanpublic MqttPahoClientFactory mqttClientFactory() {DefaultMqttPahoClientFactory factory = new DefaultMqttPahoClientFactory();MqttConnectOptions options = new MqttConnectOptions();options.setServerURIs(new String[] { "tcp://localhost:1883" });options.setUserName("your-username");options.setPassword("your-password".toCharArray());factory.setConnectionOptions(options);return factory;}@Beanpublic MessageChannel mqttInputChannel() {return new DirectChannel();}@Beanpublic MessageProducer inbound() {MqttPahoMessageDrivenChannelAdapter adapter =new MqttPahoMessageDrivenChannelAdapter("spring-boot-mqtt-client-inbound",mqttClientFactory(), "your/topic");adapter.setCompletionTimeout(5000);adapter.setConverter(new DefaultPahoMessageConverter());adapter.setQos(1);adapter.setOutputChannel(mqttInputChannel());return adapter;}@Bean@ServiceActivator(inputChannel = "mqttInputChannel")public MessageHandler handler() {return message -> {String payload = (String) message.getPayload();System.out.println("Received message: " + payload);};}@Beanpublic MessageChannel mqttOutboundChannel() {return new DirectChannel();}@Bean@ServiceActivator(inputChannel = "mqttOutboundChannel")public MessageHandler mqttOutbound() {MqttPahoMessageHandler messageHandler =new MqttPahoMessageHandler("spring-boot-mqtt-client-outbound", mqttClientFactory());messageHandler.setAsync(true);messageHandler.setDefaultTopic("your/topic");return messageHandler;}
}
4. 发送和接收消息
在你的服务或控制器中,可以使用如下方法发送消息:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.integration.support.MessageBuilder;
import org.springframework.messaging.MessageChannel;
import org.springframework.stereotype.Service;@Service
public class MqttMessageSender {@Autowiredprivate MessageChannel mqttOutboundChannel;public void sendMessage(String topic, String payload) {mqttOutboundChannel.send(MessageBuilder.withPayload(payload).setHeader("mqtt_topic", topic).build());}
}
要接收消息,可以配置handler方法中的处理逻辑,或将消息发送到另一个Spring Integration通道进行进一步处理。
5. 使用示例
在一个控制器中调用发送消息方法:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;@RestController
public class MqttController {@Autowiredprivate MqttMessageSender mqttMessageSender;@GetMapping("/send")public String send(@RequestParam String topic, @RequestParam String message) {mqttMessageSender.sendMessage(topic, message);return "Message sent to topic " + topic;}
}
这样,你就可以通过HTTP请求发送MQTT消息了。例如,访问http://localhost:8080/send?topic=test/topic&message=Hello,将消息发送到MQTT主题test/topic。
这就是一个完整的Spring Boot应用中集成MQTT的简单示例,希望对你有所帮助!
MQTT报文头介绍
MQTT协议的请求报文头非常轻量级。MQTT协议定义了固定报文头和可变报文头两部分。以下是各类报文的基本格式:
固定报文头
所有MQTT报文都有一个固定报文头,占据2-5个字节。固定报文头包含报文类型和一些控制标志。
固定报文头格式
-
第一个字节:
- 位7-4:报文类型(Message Type)
- 位3-0:标志(Flags),根据报文类型不同而不同
-
第二个字节及后续字节:
- 剩余长度(Remaining Length),表示剩余报文的字节数。采用可变长度编码,每个字节的最高位用于指示是否有后续字节。
各类报文示例
连接报文(CONNECT)
连接报文用于客户端请求与服务器建立连接。其报文头如下:
-
固定报文头:
- 第一个字节:0x10(CONNECT报文类型是1,标志位为0000)
- 第二个字节:剩余长度(根据可变部分长度而定)
-
可变报文头:
- 协议名(“MQTT”)
- 协议级别(4,表示MQTT 3.1.1)
- 连接标志(Connect Flags)
- 保持连接时间(Keep Alive)
-
有效载荷:
- 客户端标识符(Client Identifier)
- 用户名(可选)
- 密码(可选)
- 遗嘱主题(可选)
- 遗嘱消息(可选)
连接确认报文(CONNACK)
服务器响应客户端的连接请求。其报文头如下:
-
固定报文头:
- 第一个字节:0x20(CONNACK报文类型是2,标志位为0000)
- 第二个字节:剩余长度(2字节)
-
可变报文头:
- 连接确认标志(0x00或0x01)
- 返回码(0表示连接成功,其他值表示错误)
发布报文(PUBLISH)
客户端或服务器发送消息到指定主题。其报文头如下:
-
固定报文头:
- 第一个字节:0x30(PUBLISH报文类型是3,标志位根据QoS等级、重复标志和保留标志变化)
- 第二个字节:剩余长度(根据主题名、消息ID和消息体长度而定)
-
可变报文头:
- 主题名(Topic Name)
- 消息ID(QoS等级为1或2时需要)
-
有效载荷:
- 消息内容
示例
以下是一个PUBLISH报文的示例:
30 0B # 固定报文头 (PUBLISH,QoS 0)
00 05 # 主题名长度
74 6F 70 69 63 # 主题名 "topic"
68 65 6C 6C 6F # 消息内容 "hello"
在这个示例中:
- 第一个字节
0x30表示这是一个PUBLISH报文,QoS等级为0,重复标志和保留标志为0。 - 第二个字节
0x0B表示剩余长度为11个字节。 - 接下来的两个两个字节 0x00 0x05 表示主题名的长度为5个字节。
- 接下来的5个字节 0x74 0x6F 0x70 0x69 0x63 表示主题名 “topic”。
- 最后5个字节 0x68 0x65 0x6C 0x6C 0x6F 表示消息内容 “hello”。
这种结构使得MQTT报文非常紧凑和高效,特别适合物联网设备的通信。希望这篇文章能帮助你更好地理解和使用MQTT协议。
相关文章:
在Spring Boot项目中集成和使用MQTT
在物联网(IoT)应用中,MQTT(消息队列遥测传输)协议因其轻量级和高效性被广泛使用。在Spring Boot项目中,我们可以通过集成org.springframework.integration:spring-integration-mqtt依赖来实现对MQTT的支持。…...
14、设计模式之访问者模式
访问者模式 在访问者模式(Visitor Pattern)中,我们使用了一个访问者类,它改变了元素类的执行算法。通过这种方式,元素的执行算法可以随着访问者改变而改变。这种类型的设计模式属于行为型模式。根据模式,元…...
Excel如何换行不换格
在换行的字之间 按住Alt 回车...
Elasticsearch 8.1官网文档梳理 - 十五、Aggregations(聚合)
Aggregations ES 的聚合可以总结为三类:指标聚合、统计聚合、其他分析聚合。 Metric aggregations: 计算 field 的指标值,例如平均值、最大值、和等指标Bucket aggregations: 基于 field 的值、范围、或其他标准对 doc 分类&…...
计算机系统概论
目录 1. 计算机的分类 2. 计算机的发展简史 3. 计算机的硬件 1. 处理器(CPU) 2. 内存(Memory) 3. 存储设备 4. 输入输出设备 4. 计算机的软件 1. 软件的分类 1.1 系统软件 1.2 应用软件 2. 软件的特点 3. 软件开发 4…...
【Vue】diff 算法
diff的时机 当组件创建时,以及依赖的属性或数据变化时,会运行一个函数,该函数会做两件事: 运行_render生成一棵新的虚拟dom树(vnode tree),返回根节点运行_update,传入虚拟dom树的根节点,对新旧…...
Spring Boot 3.x 与 Spring Boot 2.x 的对比
Spring Boot 是 Java 开发领域的一个重要框架,它简化了基于 Spring 的应用开发。随着版本的不断更新,Spring Boot 提供了更多功能、更好的性能以及更简洁的配置。本文将详细对比 Spring Boot 3.x 和 Spring Boot 2.x,探讨它们之间的主要区别和…...
SSLError ClosedPoolError
分析日志 从您提供的日志文件内容来看,存在几个明显的问题导致了实例无法创建: SSL证书验证失败:日志中多次出现SSLError(SSLError(1, [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:897)),)错误。这表明客户端在尝试…...
勒索软件分析_Conti
0. Conti介绍 勒索软件即服务(Ransomware as a Service,RaaS)变体 Conti 推出还不到两年,已经进行了第七次迭代。Conti被证明是一种敏捷而熟练的恶意软件威胁,能够自主和引导操作,并具有无与伦比的加密速度…...
Linux系统如何通过编译方式安装python3.11.3
1.切换到/data 目录 cd /data 2.下载python源码Python-3.11.3.tgz wget https://www.python.org/ftp/python/3.11.3/Python-3.11.3.tgz tar -xzf Python-3.11.0.tgz cd Python-3.11.3 3.配置python的安装路径 和 执行openssl的路径 ./configure --prefix/usr/local/pyth…...
仿《Q极速体育》NBACBA体育直播吧足球直播综合体育直播源码
码名称:仿《Q极速体育》NBACBA体育直播吧足球直播综合体育直播源码 开发环境:帝国cms7.5 空间支持:phpmysql 仿《Q极速体育》NBACBA体育直播吧足球直播综合体育直播源码自动采集 - 我爱模板网源码名称:仿《Q极速体育》NBACBA体育直…...
代码随想录算法训练营第四天| 24. 两两交换链表中的节点、19.删除链表的倒数第N个节点 、 面试题 02.07. 链表相交、142.环形链表II
24. 两两交换链表中的节点 题目链接: 24. 两两交换链表中的节点 文档讲解:代码随想录 状态:没做出来,没有正确更新头节点,因为head和cur共享引用,会随着cur的移动,丢失之前存放的节点 错误代码&…...
吉林大学计科21级《软件工程》期末考试真题
文章目录 21级期末考试题一、单选题(2分一个,十个题,一共20分)二、问答题(5分一个,六个题,一共30分)三、分析题(一个10分,一共2个,共20分…...
AWS云服务器每月费用高昂,如何优化达到节省目的?
AWS云服务器每月费用可能因不同的使用情况和配置而有所不同。为了优化并节省AWS云服务器的费用,aws的合作伙伴九河云提供了一些建议: (1)调整实例大小:确保你使用的实例大小与你的工作负载相匹配。实例的容量每增加一倍…...
关于XtremIO 全闪存储维护的一些坑(建议)
XtremIO 是EMC过去主推的一款全闪存储系统,号称性能小怪兽,对付那些对于性能要求极高的业务场景是比较合适的,先后推出了1代和2代产品,目前这个产品好像未来的演进到了PowerStor或者PowerMax全闪,应该不独立发展这个产…...
《最新出炉》系列入门篇-Python+Playwright自动化测试-41-录制视频
宏哥微信粉丝群:https://bbs.csdn.net/topics/618423372 有兴趣的可以扫码加入 1.简介 上一篇讲解和分享了录制自动生成脚本,索性连带录制视频也一股脑的在这里就讲解和分享了。今天我们将学习如何使用Playwright和Python来录制浏览器操作的视频&#…...
一个程序员的牢狱生涯(38)答案
星期一 答 案 我被这个不知道什么时候无声无息的出现在身后的人吓出了一身的冷汗。 看到我发现了他,这个人慢慢地抬起了头……“他X的,是小X州!” 此时的小X州脸上并没有着急等待上厕所的表情,反而是用一种狡黠的眼神看着我。一直充满的敌意,现在又多了一丝威胁的神情,让…...
MySQL命令
目录 1、初级 一、连接和退出 1. 连接到 MySQL 2. 退出 MySQL 二、数据库操作 1. 显示数据库列表 2. 创建数据库 3. 使用数据库 4. 删除数据库 三、表操作 1. 显示当前数据库中的表 2. 创建表 3. 查看表结构 4. 删除表 5. 修改表 四、数据操作 1. 插入数据 2.…...
装本地知识库
装本地知识库 给大模型添加RAG知识库和搜索的功能 1.安装phidata pip install -U phidata在github将该项目拉取下来,后续步骤的很多内容可以直接使用该项目中给的例子,进行简单修改就可直接使用。 2.安装向量知识库,使用的docker docker …...
Django模板层——模板引擎配置
作为Web 框架,Django 需要一种很便利的方法以动态地生成HTML。最常见的做法是使用模板。 模板包含所需HTML 输出的静态部分,以及一些特殊的语法,描述如何将动态内容插入。 模板引擎配置 模板引擎使用该TEMPLATES设置进行配置。这是一个配置列…...
C++:std::is_convertible
C++标志库中提供is_convertible,可以测试一种类型是否可以转换为另一只类型: template <class From, class To> struct is_convertible; 使用举例: #include <iostream> #include <string>using namespace std;struct A { }; struct B : A { };int main…...
React Native 导航系统实战(React Navigation)
导航系统实战(React Navigation) React Navigation 是 React Native 应用中最常用的导航库之一,它提供了多种导航模式,如堆栈导航(Stack Navigator)、标签导航(Tab Navigator)和抽屉…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院查看报告小程序
一、开发环境准备 工具安装: 下载安装DevEco Studio 4.0(支持HarmonyOS 5)配置HarmonyOS SDK 5.0确保Node.js版本≥14 项目初始化: ohpm init harmony/hospital-report-app 二、核心功能模块实现 1. 报告列表…...
ServerTrust 并非唯一
NSURLAuthenticationMethodServerTrust 只是 authenticationMethod 的冰山一角 要理解 NSURLAuthenticationMethodServerTrust, 首先要明白它只是 authenticationMethod 的选项之一, 并非唯一 1 先厘清概念 点说明authenticationMethodURLAuthenticationChallenge.protectionS…...
css的定位(position)详解:相对定位 绝对定位 固定定位
在 CSS 中,元素的定位通过 position 属性控制,共有 5 种定位模式:static(静态定位)、relative(相对定位)、absolute(绝对定位)、fixed(固定定位)和…...
Mobile ALOHA全身模仿学习
一、题目 Mobile ALOHA:通过低成本全身远程操作学习双手移动操作 传统模仿学习(Imitation Learning)缺点:聚焦与桌面操作,缺乏通用任务所需的移动性和灵活性 本论文优点:(1)在ALOHA…...
【Go语言基础【12】】指针:声明、取地址、解引用
文章目录 零、概述:指针 vs. 引用(类比其他语言)一、指针基础概念二、指针声明与初始化三、指针操作符1. &:取地址(拿到内存地址)2. *:解引用(拿到值) 四、空指针&am…...
Java求职者面试指南:计算机基础与源码原理深度解析
Java求职者面试指南:计算机基础与源码原理深度解析 第一轮提问:基础概念问题 1. 请解释什么是进程和线程的区别? 面试官:进程是程序的一次执行过程,是系统进行资源分配和调度的基本单位;而线程是进程中的…...
【JavaSE】多线程基础学习笔记
多线程基础 -线程相关概念 程序(Program) 是为完成特定任务、用某种语言编写的一组指令的集合简单的说:就是我们写的代码 进程 进程是指运行中的程序,比如我们使用QQ,就启动了一个进程,操作系统就会为该进程分配内存…...
Ubuntu系统复制(U盘-电脑硬盘)
所需环境 电脑自带硬盘:1块 (1T) U盘1:Ubuntu系统引导盘(用于“U盘2”复制到“电脑自带硬盘”) U盘2:Ubuntu系统盘(1T,用于被复制) !!!建议“电脑…...
