springBoot集成mqtt
springBoot集成mqtt
简介
EMQX是一款大规模可弹性伸缩的云原生分布式物联网 MQTT消息服务器。
作为全球最具扩展性的 MQTT 消息服务器,EMQX 提供了高效可靠海量物联网设备连接,能够高性能实时移动与处理消息和事件流数据,帮助您快速构建关键业务的物联网平台与应用。
下载
https://www.emqx.io/downloads
注意:下载安装后可能会有打不开的情况,此时需要安装Erlang环境。
这里下载安装以windows操作系统为例。
启动
- 进入解压后的bin目录
- 输入cmd进入dos命令窗口,输入 emqx start 命令启动,出现如下说明启动成功
- 访问控制台浏览器输入 http://localhost:18083 即可访问,默认账号密码 admin/public
在控制台可以看到连接的设备相关信息
- 关闭mqtt服务, 在bin目录下 输入 emqx stop 命令。
springBoot集成mqtt
- 导入依赖
<!--mqtt中间件-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-integration</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-stream</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-mqtt</artifactId>
</dependency>
- 编写配置
mqtt:
hostUrl: tcp://127.0.0.1:1883
username: guest
password: 123456
keepAliveInterval: 60
connectionTimeout: 10
client-id: mqttClient01
server-id: mqttServer01
data-topic: /wvp_ptz
will-topic: /will
will-content: mqttServer Unexpected disconnection
completion-timeout: 10000
- 编写配置类
@Configuration
@IntegrationComponentScan
@Data
public class MqttConfig {
/**
* mqtt地址
*/
@Value("${mqtt.hostUrl}")
private String hostUrl;
/**
* 用户名
*/
@Value("${mqtt.username}")
private String username;
/**
* 密码
*/
@Value("${mqtt.password}")
private String password;
/**
* 心跳间隔
*/
@Value("${mqtt.keepAliveInterval}")
private int keepAliveInterval;
/**
*连接超时
*/
@Value("${mqtt.connectionTimeout}")
private int connectionTimeout;
/**
*客户端id
*/
@Value("${mqtt.client-id}")
private String clientId;
/**
*服务端id
*/
@Value("${mqtt.server-id}")
private String serverId;
/**
*消息主题
*/
@Value("${mqtt.data-topic}")
private String dataTopic;
/**
*遗愿主题
*/
@Value("${mqtt.will-topic}")
private String willTopic;
/**
*遗愿消息内容
*/
@Value("${mqtt.will-content}")
private String willContent;
/**
*断开连接超时时间
*/
@Value("${mqtt.completion-timeout}")
private long completionTimeout;
@Bean
public MqttConnectOptions getMqttConnectOptions(){
MqttConnectOptions options = new MqttConnectOptions();
// 设置发布端地址,多个用逗号分隔, 如:tcp://111:1883,tcp://222:1883
// 当第一个111连接上后,222不会在连,如果111挂掉后,重试连111几次失败后,会自动去连接222
options.setServerURIs(hostUrl.split(","));
options.setKeepAliveInterval(keepAliveInterval);
options.setUserName(username);
options.setPassword(password.toCharArray());
options.setConnectionTimeout(connectionTimeout);
// 设置“遗嘱”消息的话题,若客户端与服务器之间的连接意外中断,服务器将发布客户端的“遗嘱”消息。
options.setWill(willTopic,(clientId + willContent).getBytes(),1,true);
// 设置是否清空session,这里如果设置为false表示服务器会保留客户端的连接记录,
// 把配置里的 cleanSession 设为false,客户端掉线后 服务器端不会清除session,
// 当重连后可以接收之前订阅主题的消息。当客户端上线后会接受到它离线的这段时间的消息
options.setCleanSession(true);
options.setMaxInflight(1000);
//设置断开重新连接
options.setAutomaticReconnect(true);
return options;
}
@Bean
public MqttPahoClientFactory mqttPahoClientFactory(){
DefaultMqttPahoClientFactory clientFactory = new DefaultMqttPahoClientFactory();
clientFactory.setConnectionOptions(getMqttConnectOptions());
return clientFactory;
}
/**
* 发送通道
*/
@Bean
public MessageChannel mqttOutBoundChannel(){
return new DirectChannel();
}
/**
* 发送消息配置
* @return
*/
@Bean
@ServiceActivator(inputChannel = "mqttOutBoundChannel")
public MessageHandler messageHandler(){
//clientId每个连接必须唯一,否则,两个相同的clientId相互挤掉线
//String clientIdStr = clientId + new SecureRandom().nextInt(10);
MqttPahoMessageHandler mqttPahoMessageHandler = new MqttPahoMessageHandler(clientId,mqttPahoClientFactory());
//async如果为true,则调用方不会阻塞。而是在发送消息时等待传递确认。默认值为false(发送将阻塞,直到确认发送)
mqttPahoMessageHandler.setAsync(true);
mqttPahoMessageHandler.setDefaultTopic(dataTopic);
mqttPahoMessageHandler.setDefaultQos(1);
mqttPahoMessageHandler.setAsyncEvents(true);
return mqttPahoMessageHandler;
}
/**
* 接收通道
*/
@Bean
public MessageChannel mqttInboundChannel(){
return new DirectChannel();
}
/**
* 配置监听的 topic 支持通配符
* @return
*/
@Bean
public MessageProducer inBound(){
String[] topics = new String[]{
"$SYS/brokers/+/clients/+/disconnected", //客户端下线主题
"$SYS/brokers/+/clients/+/connected", //客户端上线主题
// "$exclusive/", //排它策略前缀
dataTopic,
willTopic
};
//serverId每个连接必须唯一,否则,两个相同的serverId相互挤掉线
//String serverIdStr = serverId + new SecureRandom().nextInt(10);
MqttPahoMessageDrivenChannelAdapter adapter =
new MqttPahoMessageDrivenChannelAdapter(serverId,mqttPahoClientFactory(),topics);
adapter.setOutputChannel(mqttInboundChannel());
adapter.setDisconnectCompletionTimeout(completionTimeout);
adapter.setConverter(new DefaultPahoMessageConverter());
adapter.setQos(1);
return adapter;
}
/**
* 通过通道获取数据
* @return
*/
@Bean
@ServiceActivator(inputChannel = "mqttInboundChannel")
public MessageHandler getInbound(){
MessageHandler messageHandler = new MessageHandler() {
@Override
public void handleMessage(Message<?> message) throws MessagingException {
String topic = message.getHeaders().get(MqttHeaders.RECEIVED_TOPIC).toString();
String payload = message.getPayload().toString();
//消息处理
//MyMessageHandler.msgHandler(topic,payload);
System.out.println("消息主题:"+topic+",消息内容:"+payload);
//处理订阅topic:(data/#)到的所有的数据
}
};
return messageHandler;
}
/**
* 连接失败会触发
* @param event
*/
@EventListener(classes = MqttConnectionFailedEvent.class)
public void mqttConnectFailedEvent(MqttConnectionFailedEvent event){
System.out.println("mqttConnectionFailedEvent连接mqtt失败: "+event.toString());
}
/**
* @desc 当async和async事件(async-events)都为true时,将发出MqttMessageSentEvent
* 它包含消息、主题、客户端库生成的消息id、clientId和clientInstance(每次连接客户端时递增)
* @date 2021/7/22
*@param event
* @return void
*/
@EventListener(classes = MqttMessageSentEvent.class)
public void mqttMessageSentEvent(MqttMessageSentEvent event){
System.out.println("发送消息"+event.toString());
}
/**
* @desc 当async和async事件(async-events)都为true时,将发出MqttMessageDeliveredEvent
* 当客户端库确认传递时,将发出MqttMessageDeliveredEvent。它包含messageId、clientId和clientInstance,使传递与发送相关。
* @date 2021/7/22
*@param event
* @return void
*/
@EventListener(classes = MqttMessageDeliveredEvent.class)
public void mqttMessageDeliveredEvent(MqttMessageDeliveredEvent event){
System.out.println("消息发送成功:"+event.toString());
}
/**
* @desc 成功订阅到主题,MqttSubscribedEvent事件就会被触发(多个主题,多次触发)
* @date 2021/7/22
*@param event
* @return void
*/
@EventListener(classes = MqttSubscribedEvent.class)
public void mqttSubscribedEvent(MqttSubscribedEvent event){
System.out.println("消息订阅成功:"+event.toString());
}
}
- 编写发送消息接口
@MessagingGateway(defaultRequestChannel = "mqttOutBoundChannel")
public interface MqttGateway {
/**
*
* @param data 消息
*/
void send(String data);
/**
*
* @param data 消息
* @param topic 主题
*/
void send(String data, @Header(MqttHeaders.TOPIC) String topic);
/**
*
* @param data 消息
* @param topic 主题
* @param qos 消息质量
*/
void send(String data, @Header(MqttHeaders.TOPIC) String topic,@Header(MqttHeaders.QOS) int qos);
}
- 编写 TestController
@RestController
public class TestController {
@Autowired
private MqttGateway mqttGateway;
@RequestMapping("/test")
public String testMqtt(@RequestParam(value = "msg") String msg){
mqttGateway.send(msg,"/wvp_ptz",1);
return "ok";
}
}
- postman测试
idea控制台
mqtt面板
结束
到此springBoot已经集成mqtt了
本文来自博客园,作者:cxf0616,转载请注明原文链接:https://www.cnblogs.com/cxfbk/p/17191564.html
风起于青萍之末,浪成于微澜之间
每一份成功都源于每日的坚持