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的更多相关文章

  1. SpringBoot 集成MQTT配置

    目录 1. 前言 2. MQTT介绍 3. SpringBoot 集成MQTT 3.1 导入mqtt库 3.2 配置MQTT订阅者 3.3 配置MQTT发布者 3.4 MQTT消息处理和发送 3.4. ...

  2. 物联网架构成长之路(32)-SpringBoot集成MQTT客户端

    一.前言 这里虽然是说MQTT客户端.其实对于服务器来说,这里的一个具有超级权限的MQTT客户端,就可以做很多事情.比如手机APP或者网页或者第三方服务需要发送数据到设备,但是这些又不是设备,又不能让 ...

  3. Spring Boot 集成 MQTT

    本文代码有些许问题,处理方案见:解决 spring-integration-mqtt 频繁报 Lost connection 错误 一.添加配置 spring: mqtt: client: usern ...

  4. 【springBoot】springBoot集成redis的key,value序列化的相关问题

    使用的是maven工程 springBoot集成redis默认使用的是注解,在官方文档中只需要2步; 1.在pom文件中引入即可 <dependency> <groupId>o ...

  5. SpringBoot集成security

    本文就SpringBoot集成Security的使用步骤做出解释说明.

  6. springboot集成Actuator

    Actuator监控端点,主要用来监控与管理. 原生端点主要分为三大类:应用配置类.度量指标类.操作控制类. 应用配置类:获取应用程序中加载的配置.环境变量.自动化配置报告等与SpringBoot应用 ...

  7. SpringBoot集成Shiro并用MongoDB做Session存储

    之前项目鉴权一直使用的Shiro,那是在Spring MVC里面使用的比较多,而且都是用XML来配置,用Shiro来做权限控制相对比较简单而且成熟,而且我一直都把Shiro的session放在mong ...

  8. SpringBoot集成redis的key,value序列化的相关问题

    使用的是maven工程 springBoot集成redis默认使用的是注解,在官方文档中只需要2步; 1.在pom文件中引入即可 <dependency> <groupId>o ...

  9. springboot集成mybatis(二)

    上篇文章<springboot集成mybatis(一)>介绍了SpringBoot集成MyBatis注解版.本文还是使用上篇中的案例,咱们换个姿势来一遍^_^ 二.MyBatis配置版(X ...

  10. springboot集成mybatis(一)

    MyBatis简介 MyBatis本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation迁移到了google code,并且改名为MyB ...

随机推荐

  1. C语言:卖鸭子问题---递归法实现

    1.一个人赶着鸭子去每个村庄卖,每经过一个村子卖去所赶鸭子的一半又一只.这样他经过了七个村子后还剩两只鸭子,问他出发时共赶多少只鸭子?经过每个村子卖出多少只鸭子? 代码: #include<st ...

  2. ❤️‍🔥 Solon Cloud Event 新的事务特性与应用

    1.Solon Cloud Event? 是 Solon 分布式事件总线的解决方案.也是 Solon "最终一致性"分布式事务的解决方案之一 2.事务特性 事务?就是要求 Even ...

  3. 推荐一款模拟浏览器自动化操作神器!Mechanize

    大家好,我是狂师! 今天给大家推荐一款用于模拟浏览器行为以进行网页自动化操作Python库:Mechanize. 1.介绍 Mechanize是Python中的一个库,它被设计用来自动化网页浏览和数据 ...

  4. 深入理解 Swoole 的底层加载原理

    首发原文链接:深入理解 Swoole 的底层加载原理 PHP 扩展加载 我们从 php-src/sapi/cli/php_cli.c:1159 文件的入口函数 int main(int argc, c ...

  5. Django----模型----数据库的基本操作

    1.添加记录 方式一:save() 方式二(推荐):create() 2.查询记录 (1)all() 查询所有记录,返回queryset对象. stu_list = Student.objects.a ...

  6. 【分享】FFmpeg桌面神器,集多种功能于一身,超级好用,不用命令行!

    在媒体处理上,市面上有很多软件可以选择,在众多软件里面 FFmpeg 是比较独特的一款,直接选择 FFmpeg 硬核命令行工具的朋友相对较少,大多时候只是被集成在各样的软件里,如果单独拿出来使用,不少 ...

  7. Flutter(六):Flutter_Boost接入现有原生工程(iOS+Android)

    本篇博客会介绍如何通过第三方插件Flutter_Boost实现接入原有工程. 如果不希望引入第三方插件,可以参考博客Flutter混合开发--接入现有原生工程(iOS+Android) 一.新建原生工 ...

  8. HashMap设置初始容量一直都用错了?

    1 背景 今天在代码审查的时候,发现一位离职的同事留下了这样一串代码: Map<String,String> map = new HashMap<>((int)(list.si ...

  9. .Net Core 部署IIS

    我相信很多人看了其他的贴子,都没有成功部署,因为里面有很多暗坑.接下来博主就一步一步给大家讲明白,带领大家部署 先基本的发布 操作:右击web项目的<发布>按钮.选文件 配置发布属性    ...

  10. 异步长传文件插件 jquery validate 前端验证

    异步文件上传插件:http://fex.baidu.com/webuploader/getting-started.html html5 FormData 可以实现无刷新上传  有空了解 FileRe ...