mqtt发布和订阅消息
mqtt连接信息配置:
mqtt_username=×××××
#MQTT-密码,需要解密
mqtt_password=×××××
mqtt_url=tcp://ip:1883
#MQTT-订阅的主题
mqtt_default_topic=×××××××
#两个客户端的clientId不能相同,生产者和消费者的clientId不能相同
mqtt_client_id=×××××
mqtt_completionTimeout=1000
创建连接,生产者和消费者配置
import com.hikvision.yqclgk.util.BlockThreadPool;
import com.hikvision.yqclgk.util.MyRunable;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.integration.annotation.IntegrationComponentScan;
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.Message;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.MessageHandler;
import org.springframework.messaging.MessagingException;
/**
*〈MQTT接收消息处理〉
* **/
@Slf4j
@Configuration
@IntegrationComponentScan
public class MqttReceiveClient {
@Autowired
BlockThreadPool blockThreadPool;
@Value("${mqtt_username}")
private String username;
@Value("${mqtt_password}")
private String password;
@Value("${mqtt_url}")
private String hostUrl;
@Value("${mqtt_client_id}")
private String clientId;
//订阅主题(#订阅主题,多个用‘,’隔开,如:topic,YIHON_WQ_M)
@Value("${mqtt_default_topic}")
private String defaultTopic;
@Value("${mqtt_completionTimeout}")
private int completionTimeout; //连接超时
@Bean(value = "getMqttConnectOptions")
public MqttConnectOptions getMqttConnectOptions() {
MqttConnectOptions mqttConnectOptions = new MqttConnectOptions();
mqttConnectOptions.setUserName(username);
mqttConnectOptions.setPassword(password.toCharArray());
mqttConnectOptions.setServerURIs(new String[]{hostUrl});
//cleanSession 设为 true;当客户端掉线时;服务器端会清除 客户端session;重连后 客户端会有一个新的session,cleanSession
// 设为false,客户端掉线后 服务器端不会清除session,当重连后可以接收之前订阅主题的消息。当客户端上线后会接受到它离线的这段时间的消息
mqttConnectOptions.setCleanSession(false);
// 设置会话心跳时间 单位为秒
mqttConnectOptions.setKeepAliveInterval(2);
return mqttConnectOptions;
}
@Bean
public MqttPahoClientFactory mqttClientFactory() {
DefaultMqttPahoClientFactory factory = new DefaultMqttPahoClientFactory();
factory.setConnectionOptions(getMqttConnectOptions());
return factory;
}
//接收通道
@Bean
public MessageChannel mqttInputChannel() {
return new DirectChannel();
}
//配置client,监听的topic
@Bean
public MessageProducer inbound() {
MqttPahoMessageDrivenChannelAdapter adapter =
new MqttPahoMessageDrivenChannelAdapter(clientId + "_inbound2", mqttClientFactory(), defaultTopic.trim().split(","));
adapter.setCompletionTimeout(completionTimeout);
adapter.setConverter(new DefaultPahoMessageConverter());
adapter.setQos(2);
adapter.setOutputChannel(mqttInputChannel());
return adapter;
}
//通过通道获取数据
@Bean
@ServiceActivator(inputChannel = "mqttInputChannel")
public MessageHandler handler() {
return new MessageHandler() {
@Override
public void handleMessage(Message<?> message) throws MessagingException {
log.info("主题:{},QOS:{},消息接收到的数据:{}", message.getHeaders().get(MqttHeaders.RECEIVED_TOPIC), message.getHeaders().get(MqttHeaders.RECEIVED_QOS), message.getPayload());
}
};
}
//生产者
@Bean
@ServiceActivator(inputChannel = "mqttOutboundChannel")
public MessageHandler mqttOutbound() {
MqttPahoMessageHandler messageHandler = new MqttPahoMessageHandler(clientId, mqttClientFactory());
messageHandler.setDefaultTopic(defaultTopic);
//如果设置成true,即异步,发送消息时将不会阻塞。
messageHandler.setAsync(true);
//设置默认QoS
messageHandler.setDefaultQos(0);
DefaultPahoMessageConverter defaultPahoMessageConverter = new DefaultPahoMessageConverter();
//发送默认按字节类型发送消息
// defaultPahoMessageConverter.setPayloadAsBytes(true);
messageHandler.setConverter(defaultPahoMessageConverter);
return messageHandler;
}
@Bean
public MessageChannel mqttOutboundChannel() {
return new DirectChannel();
}
}
import org.springframework.integration.annotation.MessagingGateway;
import org.springframework.integration.mqtt.support.MqttHeaders;
import org.springframework.messaging.handler.annotation.Header;
@MessagingGateway(defaultRequestChannel = "mqttOutboundChannel")
public interface TestGateway {
// void sendToMqtt(String data,@Header(MqttHeaders.TOPIC) String topic);
// 定义重载方法,用于消息发送
void sendToMqtt(String payload);
// 指定topic进行消息发送
void sendToMqtt(@Header(MqttHeaders.TOPIC) String topic, String payload);
void sendToMqtt(@Header(MqttHeaders.TOPIC) String topic, @Header(MqttHeaders.QOS) int qos, String payload);
void sendToMqtt(@Header(MqttHeaders.TOPIC) String topic, @Header(MqttHeaders.QOS) int qos, byte[] payload);
}
往mqtt发送消息测试:
@Autowired
private TestGateway mqttGateway;
@GetMapping("/testMqtt")
public String sendMqtt(@RequestParam(value = "topic") String topic, @RequestParam(value = "message") String message) {
mqttGateway.sendToMqtt(topic, message);
return "SUCCESS";
}
用postman调用该方法,即可。