<dependency>
<groupId>org.springframework.integrationgroupId>
<artifactId>spring-integration-streamartifactId>
dependency>
<dependency>
<groupId>org.springframework.integrationgroupId>
<artifactId>spring-integration-mqttartifactId>
dependency>
mqtt:
enabled: true
host: tcp://localhost:1883
username: admin
pwd: admin
package com.zhk.study.mqtt;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.integration.mqtt.core.DefaultMqttPahoClientFactory;
import org.springframework.integration.mqtt.core.MqttPahoClientFactory;
/**
* mqtt消息处理配置
*/
@Configuration
@ConditionalOnProperty(value = "mqtt.enabled", havingValue = "true")
public class MqttBaseConfig {
@Value("${mqtt.host}")
private String mqttHost;
@Value("${mqtt.username:}")
private String mqttUserName;
@Value("${mqtt.pwd:}")
private String mqttPwd;
/**
* 构造一个默认的mqtt客户端操作bean
*
* @return
*/
@Bean
public MqttPahoClientFactory factory(){
DefaultMqttPahoClientFactory defaultMqttPahoClientFactory = new DefaultMqttPahoClientFactory();
MqttConnectOptions mqttConnectOptions = new MqttConnectOptions();
mqttConnectOptions.setUserName(mqttUserName);
mqttConnectOptions.setPassword(mqttPwd.toCharArray());
mqttConnectOptions.setServerURIs(new String[]{mqttHost});
defaultMqttPahoClientFactory.setConnectionOptions(mqttConnectOptions);
return defaultMqttPahoClientFactory;
}
}
package com.zhk.study.mqtt;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
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.mqtt.core.MqttPahoClientFactory;
import org.springframework.integration.mqtt.outbound.MqttPahoMessageHandler;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.MessageHandler;
/**
* mqtt出站消息处理配置
*/
@Configuration
@ConditionalOnProperty(value = "mqtt.enabled", havingValue = "true")
public class MqttOutConfig {
/**
* mqtt消息出站通道,用于发送出站消息
*
* @return
*/
@Bean
public MessageChannel mqttOutputChannel() {
return new DirectChannel();
}
/**
* mqtt消息出站通道默认配置,用于向外发出mqtt消息,当前案例中发到了同一个mqtt服务器
*
* @return
*/
@Bean
@ServiceActivator(inputChannel = "mqttOutputChannel")
public MessageHandler mqttOutbound(MqttPahoClientFactory factory) {
String clientId = "h-backend-mqtt-out-" + System.currentTimeMillis();
MqttPahoMessageHandler messageHandler = new MqttPahoMessageHandler(clientId, factory);
messageHandler.setAsync(true);
messageHandler.setDefaultQos(2);
messageHandler.setDefaultTopic("/crane/mqtt/demo/foo");
return messageHandler;
}
}
package com.zhk.study.mqtt;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.integration.mqtt.support.MqttHeaders;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageHandler;
import org.springframework.messaging.MessagingException;
import org.springframework.stereotype.Component;
/**
* mqtt订阅消息处理
*/
@Component
@ConditionalOnProperty(value = "mqtt.enabled", havingValue = "true")
public class MqttMessageReceiver implements MessageHandler {
private Logger logger = LoggerFactory.getLogger(this.getClass());
@Override
public void handleMessage(Message<?> message) throws MessagingException {
String topic = String.valueOf(message.getHeaders().get(MqttHeaders.RECEIVED_TOPIC));
String payload = String.valueOf(message.getPayload());
logger.info("接收到 mqtt消息,主题:{} 消息:{}", topic, payload);
}
}
package com.zhk.study.mqtt;
import lombok.RequiredArgsConstructor;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
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.MqttPahoClientFactory;
import org.springframework.integration.mqtt.inbound.MqttPahoMessageDrivenChannelAdapter;
import org.springframework.integration.mqtt.support.DefaultPahoMessageConverter;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.MessageHandler;
@Configuration
@ConditionalOnProperty(value = "mqtt.enabled", havingValue = "true")
@RequiredArgsConstructor
public class MqttInConfig {
private final MqttMessageReceiver mqttMessageReceiver;
/**
* mqtt消息入站通道,订阅消息后消息进入的通道。
* 可创建多个入站通道,对应多个不同的消息生产者。
*
* @return
*/
@Bean
public MessageChannel mqttInputChannel() {
return new DirectChannel();
}
/**
* 对于当前应用来讲,接收的mqtt消息的生产者。将生产者绑定到mqtt入站通道,即通过入站通道进入的消息为生产者生产的消息。
* 可创建多个消息生产者,对应多个不同的消息入站通道,同时生产者监听不同的topic
*
* @return
*/
@Bean
public MessageProducer channelInbound(MessageChannel mqttInputChannel, MqttPahoClientFactory factory) {
String clientId = "h-backend-mqtt-in-" + System.currentTimeMillis();
MqttPahoMessageDrivenChannelAdapter adapter = new MqttPahoMessageDrivenChannelAdapter(clientId, factory, "/crane/mqtt/demo/#");
adapter.setCompletionTimeout(5000);
adapter.setConverter(new DefaultPahoMessageConverter());
adapter.setQos(2);
adapter.setOutputChannel(mqttInputChannel);
return adapter;
}
/**
* mqtt入站消息处理工具,对于指定消息入站通道接收到生产者生产的消息后处理消息的工具。
*
* @return
*/
@Bean
@ServiceActivator(inputChannel = "mqttInputChannel")
public MessageHandler mqttMessageHandler() {
return this.mqttMessageReceiver;
}
}
package com.zhk.study.mqtt;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.integration.annotation.MessagingGateway;
import org.springframework.integration.mqtt.support.MqttHeaders;
import org.springframework.messaging.handler.annotation.Header;
import org.springframework.stereotype.Component;
/**
* mqtt消息发送工具,指定通过某个通道发出消息
*/
@Component
@ConditionalOnProperty(value = "mqtt.enabled", havingValue = "true")
@MessagingGateway(defaultRequestChannel = "mqttOutputChannel")
public interface MqttMessageSender {
/**
* 发送信息
*
* @param data 发送的消息
*/
void sendToMqtt(String data);
/**
* 指定主题发送消息
*
* @param topic 主题
* @param payload 消息主体
*/
void sendToMqtt(@Header(MqttHeaders.TOPIC) String topic, String payload);
/**
* 指定主题、qos发送消息
*
* @param topic 主题
* @param qos 对消息处理的几种机制。
* 0 表示的是订阅者没收到消息不会再次发送,消息会丢失。
* 1 表示的是会尝试重试,一直到接收到消息,但这种情况可能导致订阅者收到多次重复消息。
* 2 多了一次去重的动作,确保订阅者收到的消息有一次。
* @param payload 消息主体
*/
void sendToMqtt(@Header(MqttHeaders.TOPIC) String topic, @Header(MqttHeaders.QOS) int qos, String payload);
}
package com.zhk.study.mqtt;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@ConditionalOnProperty(value = "mqtt.enabled", havingValue = "true")
@RequestMapping("/public/mqtt")
public class MqttController {
private Logger logger = LoggerFactory.getLogger(this.getClass());
private final MqttMessageSender mqttMessageSender;
public MqttController(MqttMessageSender mqttMessageSender) {
this.mqttMessageSender = mqttMessageSender;
}
/**
* 发送mqtt消息
*
* @param topic 消息主题
* @param data 消息内容
* @return
*/
@GetMapping("/send")
public String send(String topic, String data) {
if (StringUtils.isNotBlank(topic)) {
this.mqttMessageSender.sendToMqtt(topic, data);
} else {
this.mqttMessageSender.sendToMqtt(data);
}
return "success";
}
}
疑问点可以直接给博主发消息,看到就回复,此帖转发别人的。注意点这个监听绑定在MqttInConfig中
MqttPahoMessageDrivenChannelAdapter adapter = new MqttPahoMessageDrivenChannelAdapter(clientId, factory, "/crane/mqtt/demo/#");