SpringBoot集成MQTT
MQTT介绍
MQTT 是基于 Publish/Subscribe(发布/订阅) 模式的物联网通信协议,凭借简单易实现、支持 QoS、报文小等特点。

其具有协议简洁、⼩巧、可扩展性强、省流量、省电等优点,⽽且已经有PHP,JAVA,Python,C,C#,Go等多个语⾔版本,基本可以使⽤在任何平台上,⼏乎可以把所有联⽹物品和外部连接起来,所以特别适合⽤来当做物联⽹的通信协议。
MQTT特点
MQTT协议是为⼤量计算能⼒有限,且⼯作在低带宽、不可靠的⽹络的远程传感器和控制设备通讯⽽设计的协议,它具有以下主要的⼏项特性:
- 使⽤发布/订阅消息模式,提供⼀对多的消息发布,解除应⽤程序耦合;
- 对负载内容屏蔽的消息传输;
- 使⽤ TCP/IP 提供⽹络连接;
- 有三种消息发布服务质量:
“⾄多⼀次”,消息发布完全依赖底层 TCP/IP ⽹络。会发⽣消息丢失或重复。这⼀级别可⽤于如下情况,环境传感器数据,丢失⼀次读,记录⽆所谓,因为不久后还会有第⼆次发送。
“⾄少⼀次”,确保消息到达,但消息重复可能会发⽣。
“只有⼀次”,确保消息到达⼀次。这⼀级别可⽤于如下情况,在计费系统中,消息重复或丢失会导致不正确的结果。
- ⼩型传输,开销很⼩(固定长度的头部是 2 字节),协议交换最⼩化,以降低⽹络流量;(用极少的代码和有限的带宽,为连接远程设备提供实时可靠的消息服务。)
- 使⽤ Last Will 和 Testament 特性通知有关各⽅客户端异常中断的机制;
MQTT应用场景
作为一种低开销、低带宽占用的即时通讯协议,使其在物联网、小型设备、移动应用等方面有较广泛的应用。
java通过代码连接MQTT服务器,进行采集数据接收、解析、业务处理、存储入库、数据展示。
消息推送: ⽐如PC端的推送⼴告,⽐如安卓的推送服务,还有⼀些即时通信软件如微信、易信等也是采⽤的推送技术。
智能点餐: 通过MQTT消息队列产品,消费者可在餐桌上扫码点餐,并与商家后端系统连接实现自助下单、支付。
信息更新: 实现商场超市等场所的电子标签、公共场所的多媒体屏幕的显示更新管理。
扫码出站: 最常见的停车场扫码缴费,自动起竿;地铁闸口扫码进出站。

MQTT角色组成
1、服务端(Broker)
EMQX就是一个MQTT的Broker,emqx只是基于erlang语言开发的软件而已,其它的MQ还有ActiveMQ、RabbitMQ、HiveMQ等等。
EMQX服务端:https://www.emqx.io/zh/downloads?os=Windows
2、客户端(发布/订阅)
EMQX客户端:https://mqttx.app/zh
通过java代码来实现我们消息的生产者和消费者。
引入mqtt依赖
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-mqtt</artifactId>
</dependency>
生产者(发布)
修改配置文件
server:
port: 8081
spring:
application:
name: provider
# MQTT配置信息
mqtt:
# MQTT服务地址,端口号默认11883,如果有多个,用逗号隔开
url: tcp://127.0.0.1:11883
# 用户名
username: admin
# 密码
password: 123456
# 客户端id(不能重复)
client:
id: provider-id
# MQTT默认的消息推送主题,实际可在调用接口是指定
default:
topic: topic
消息发布者客户端配置
@Configuration
@Slf4j
public class MqttProviderConfig {
@Value("${spring.mqtt.username}")
private String username;
@Value("${spring.mqtt.password}")
private String password;
@Value("${spring.mqtt.url}")
private String hostUrl;
@Value("${spring.mqtt.client.id}")
private String clientId;
@Value("${spring.mqtt.default.topic}")
private String defaultTopic;
/**
* 客户端对象
*/
private MqttClient client;
/**
* 在bean初始化后连接到服务器
*/
@PostConstruct
public void init(){
connect();
}
/**
* 客户端连接服务端
*/
public void connect(){
try{
//创建MQTT客户端对象
client = new MqttClient(hostUrl,clientId,new MemoryPersistence());
//连接设置
MqttConnectOptions options = new MqttConnectOptions();
//是否清空session,设置false表示服务器会保留客户端的连接记录(订阅主题,qos),客户端重连之后能获取到服务器在客户端断开连接期间推送的消息
//设置为true表示每次连接服务器都是以新的身份
options.setCleanSession(true);
//设置连接用户名
options.setUserName(username);
//设置连接密码
options.setPassword(password.toCharArray());
//设置超时时间,单位为秒
options.setConnectionTimeout(100);
//设置心跳时间 单位为秒,表示服务器每隔 1.5*20秒的时间向客户端发送心跳判断客户端是否在线
options.setKeepAliveInterval(20);
//设置遗嘱消息的话题,若客户端和服务器之间的连接意外断开,服务器将发布客户端的遗嘱信息
options.setWill("willTopic",(clientId + "与服务器断开连接").getBytes(),0,false);
//设置回调
client.setCallback(new MqttProviderCallBack());
client.connect(options);
} catch(MqttException e){
e.printStackTrace();
}
}
public void publish(int qos,boolean retained,String topic,String message){
MqttMessage mqttMessage = new MqttMessage();
mqttMessage.setQos(qos);
mqttMessage.setRetained(retained);
mqttMessage.setPayload(message.getBytes());
//主题的目的地,用于发布/订阅信息
MqttTopic mqttTopic = client.getTopic(topic);
//提供一种机制来跟踪消息的传递进度
//用于在以非阻塞方式(在后台运行)执行发布是跟踪消息的传递进度
MqttDeliveryToken token;
try {
//将指定消息发布到主题,但不等待消息传递完成,返回的token可用于跟踪消息的传递状态
//一旦此方法干净地返回,消息就已被客户端接受发布,当连接可用,将在后台完成消息传递。
token = mqttTopic.publish(mqttMessage);
token.waitForCompletion();
} catch (MqttException e) {
e.printStackTrace();
}
}
}
消息发布客户端回调
@Configuration
public class MqttProviderCallBack implements MqttCallback{
@Value("${spring.mqtt.client.id}")
private String clientId;
/**
* 与服务器断开的回调
*/
@Override
public void connectionLost(Throwable cause) {
System.out.println(clientId+"与服务器断开连接");
}
/**
* 消息到达的回调
*/
@Override
public void messageArrived(String topic, MqttMessage message) throws Exception {
}
/**
* 消息发布成功的回调
*/
@Override
public void deliveryComplete(IMqttDeliveryToken token) {
IMqttAsyncClient client = token.getClient();
System.out.println(client.getClientId()+"发布消息成功!");
}
}
创建控制器测试发布信息
@Controller
public class SendController {
@Autowired
private MqttProviderConfig providerClient;
@RequestMapping("/sendMessage")
@ResponseBody
public String sendMessage(int qos,boolean retained,String topic,String message){
try {
providerClient.publish(qos, retained, topic, message);
return "发送成功";
} catch (Exception e) {
e.printStackTrace();
return "发送失败";
}
}
}
消费者(订阅)
修改配置文件
server:
port: 8082
spring:
application:
name: consumer
# MQTT配置信息
mqtt:
# MQTT服务端地址,端口默认为11883,如果有多个,用逗号隔开
url: tcp://127.0.0.1:11883
# 用户名
username: admin
# 密码
password: 123456
# 客户端id(不能重复)
client:
id: consumer-id
# MQTT默认的消息推送主题,实际可在调用接口时指定
default:
topic: topic
接收者客户端配置
@Configuration
public class MqttConsumerConfig {
@Value("${spring.mqtt.username}")
private String username;
@Value("${spring.mqtt.password}")
private String password;
@Value("${spring.mqtt.url}")
private String hostUrl;
@Value("${spring.mqtt.client.id}")
private String clientId;
@Value("${spring.mqtt.default.topic}")
private String defaultTopic;
/**
* 客户端对象
*/
private MqttClient client;
/**
* 在bean初始化后连接到服务器
*/
@PostConstruct
public void init(){
connect();
}
/**
* 客户端连接服务端
*/
public void connect(){
try {
//创建MQTT客户端对象
client = new MqttClient(hostUrl,clientId,new MemoryPersistence());
//连接设置
MqttConnectOptions options = new MqttConnectOptions();
//是否清空session,设置为false表示服务器会保留客户端的连接记录,客户端重连之后能获取到服务器在客户端断开连接期间推送的消息
//设置为true表示每次连接到服务端都是以新的身份
options.setCleanSession(true);
//设置连接用户名
options.setUserName(username);
//设置连接密码
options.setPassword(password.toCharArray());
//设置超时时间,单位为秒
options.setConnectionTimeout(100);
//设置心跳时间 单位为秒,表示服务器每隔1.5*20秒的时间向客户端发送心跳判断客户端是否在线
options.setKeepAliveInterval(20);
//设置遗嘱消息的话题,若客户端和服务器之间的连接意外断开,服务器将发布客户端的遗嘱信息
options.setWill("willTopic",(clientId + "与服务器断开连接").getBytes(),0,false);
//设置回调
client.setCallback(new MqttConsumerCallBack());
client.connect(options);
//订阅主题
//消息等级,和主题数组一一对应,服务端将按照指定等级给订阅了主题的客户端推送消息
int[] qos = {1,1};
//主题
String[] topics = {"topic1","topic2"};
//订阅主题
client.subscribe(topics,qos);
} catch (MqttException e) {
e.printStackTrace();
}
}
/**
* 断开连接
*/
public void disConnect(){
try {
client.disconnect();
} catch (MqttException e) {
e.printStackTrace();
}
}
/**
* 订阅主题
*/
public void subscribe(String topic,int qos){
try {
client.subscribe(topic,qos);
} catch (MqttException e) {
e.printStackTrace();
}
}
}
消息接收者客户端回调
package com.lyp.mqttconsumer.mqtt;
import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.MqttCallback;
import org.eclipse.paho.client.mqttv3.MqttMessage;
public class MqttConsumerCallBack implements MqttCallback{
/**
* 客户端断开连接的回调
*/
@Override
public void connectionLost(Throwable throwable) {
System.out.println("与服务器断开连接,可重连");
}
/**
* 消息到达的回调
*/
@Override
public void messageArrived(String topic, MqttMessage message) throws Exception {
System.out.println(String.format("接收消息主题 : %s",topic));
System.out.println(String.format("接收消息Qos : %d",message.getQos()));
System.out.println(String.format("接收消息内容 : %s",new String(message.getPayload())));
System.out.println(String.format("接收消息retained : %b",message.isRetained()));
}
/**
* 消息发布成功的回调
*/
@Override
public void deliveryComplete(IMqttDeliveryToken iMqttDeliveryToken) {
}
}
控制器控制手动建立和断开连接方法
@Controller
public class TestController {
@Autowired
private MqttConsumerConfig client;
@Value("${spring.mqtt.client.id}")
private String clientId;
@RequestMapping("/connect")
@ResponseBody
public String connect(){
client.connect();
return clientId + "连接到服务器";
}
@RequestMapping("/disConnect")
@ResponseBody
public String disConnect(){
client.disConnect();
return clientId + "与服务器断开连接";
}
}
SpringBoot集成MQTT的更多相关文章
- SpringBoot 集成MQTT配置
目录 1. 前言 2. MQTT介绍 3. SpringBoot 集成MQTT 3.1 导入mqtt库 3.2 配置MQTT订阅者 3.3 配置MQTT发布者 3.4 MQTT消息处理和发送 3.4. ...
- 物联网架构成长之路(32)-SpringBoot集成MQTT客户端
一.前言 这里虽然是说MQTT客户端.其实对于服务器来说,这里的一个具有超级权限的MQTT客户端,就可以做很多事情.比如手机APP或者网页或者第三方服务需要发送数据到设备,但是这些又不是设备,又不能让 ...
- Spring Boot 集成 MQTT
本文代码有些许问题,处理方案见:解决 spring-integration-mqtt 频繁报 Lost connection 错误 一.添加配置 spring: mqtt: client: usern ...
- 【springBoot】springBoot集成redis的key,value序列化的相关问题
使用的是maven工程 springBoot集成redis默认使用的是注解,在官方文档中只需要2步; 1.在pom文件中引入即可 <dependency> <groupId>o ...
- SpringBoot集成security
本文就SpringBoot集成Security的使用步骤做出解释说明.
- springboot集成Actuator
Actuator监控端点,主要用来监控与管理. 原生端点主要分为三大类:应用配置类.度量指标类.操作控制类. 应用配置类:获取应用程序中加载的配置.环境变量.自动化配置报告等与SpringBoot应用 ...
- SpringBoot集成Shiro并用MongoDB做Session存储
之前项目鉴权一直使用的Shiro,那是在Spring MVC里面使用的比较多,而且都是用XML来配置,用Shiro来做权限控制相对比较简单而且成熟,而且我一直都把Shiro的session放在mong ...
- SpringBoot集成redis的key,value序列化的相关问题
使用的是maven工程 springBoot集成redis默认使用的是注解,在官方文档中只需要2步; 1.在pom文件中引入即可 <dependency> <groupId>o ...
- springboot集成mybatis(二)
上篇文章<springboot集成mybatis(一)>介绍了SpringBoot集成MyBatis注解版.本文还是使用上篇中的案例,咱们换个姿势来一遍^_^ 二.MyBatis配置版(X ...
- springboot集成mybatis(一)
MyBatis简介 MyBatis本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation迁移到了google code,并且改名为MyB ...
随机推荐
- 80x86汇编—分支循环程序设计
文章目录 查表法: 实现16进制数转ASCII码显示 计算AX的绝对值 判断有无实根 地址表形成多分支 从100,99,...,2,1倒序累加 输入一个字符,然后输出它的二进制数 大小写转换 大写转小 ...
- Google出品的NotebookLM 人工智能笔记本,一款基于RAG的personalized AI产品
Google推出了实验性的NotebookLM产品,一款基于RAG的个性化AI助手产品,基于用户提供的可信信息,通过RAG,帮助用户洞察和学习参考内容,然后借助AI整理笔记,转换为用户最终需要的大纲. ...
- supersocket实际应用之你画我猜游戏(一)
supersocket这款组件,让不懂tcp/ip的人都能开发出网络应用.我们不必在开发与自己主要应用不相关的代码了,主要精力都能放在设计业务逻辑上面了. 现在使用现成又完备的组件,真是大大的提高了开 ...
- volatile关键字到底有什么作用
提示:更多优秀博文请移步博主的GitHub仓库:GitHub学习笔记.Gitee学习笔记 volatile是Java提供的一种轻量级的同步机制.Java 语言包含两种内在的同步机制:同步块(或方法)和 ...
- 5分钟明白LangChain 的输出解析器和链
本文介绍 LangChain 的输出解析器OutputParser的使用,和基于LangChain的LCEL构建链. 1. 输出解析器OutputParser 1.1.为什么需要OutputParse ...
- Android 13 - Media框架(18)- CodecBase
关注公众号免费阅读全文,进入音视频开发技术分享群! 从这一节开始我们会回到上层来看ACodec的实现,在这之前我们会先了解ACodec的基类CodecBase.CodecBase.h 中除了声明有自身 ...
- Android 13 - Media框架(8)- MediaExtractor(2)
关注公众号免费阅读全文,进入音视频开发技术分享群! 上一篇 MediaExtractor 笔记中我们学习了 extractor 以及 source 调用的层次结构,这一节我们会看一看部分的实现细节. ...
- PaddleOCR在 Linux下的webAPI部署方案
很多小伙伴在使用OCR时都希望能过采用API的方式调用,这样就可以跨端跨平台了.本文将介绍一种基于python的PaddleOCR识方案.喜欢的可以关注公众号,获取更多内容. 一. Linux环境下部 ...
- 安装centos7模板机[正常版]
1. 安装centos 7模板机 准备好centos7的镜像 下载地址:http://mirrors.aliyun.com/centos/7/isos/x86_64/ 安装centos 自定义硬件: ...
- k8s集群创建阿里云版本
阿里云创建k8s集群实例 创建两个8G内存的抢占实例(青岛),能ssh 默认关闭防火墙,且没有交换分区 配置/etc/hosts,主机名 配置k8s仓库 配置命令补全 安装docker(需要conta ...