一、需求
接口中发送设备调用消息后,等待设备响应消息返回后,继续向下执行。
二、解决方案
采用redis的发布+订阅功能实现
分四步:
1. 发送mqtt消息后,临时注册一个redis监听器,订阅指定的key,并设置超时时长
2. 设备收到执行消息后,将执行结果作为响应消息,提交到mqtt
3. 服务端收到响应消息后,发布数据到redis
4. redis监听到key变更后,向下执行。
三、实现过程
1. 添加依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
2. 配置redis监听器
@Configuration
public class RedisListenerConfig {
@Bean
RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory){
RedisMessageListenerContainer container=new RedisMessageListenerContainer();
container.setConnectionFactory(connectionFactory);
return container;
}
}
@Slf4j
public class MessageReceiverListener implements MessageListener {
private Semaphore latch = new Semaphore(0);
private String unlockMessage = "0";
@Override
public void onMessage(Message message, byte[] pattern) {
String msg= new String(message.getBody());
if (unlockMessage.equals(msg)) {
latch.release();
}
}
public Semaphore getLatch() {
return latch;
}
}
3. 收到消息后创建redis数据
redisTemplate.opsForValue().set(key,value,500l,TimeUnit.MILLISECONDS);
redisTemplate.convertAndSend(key, "0");
4. 接口实现
producer.send(topic, value);
MessageReceiverListener listener = new MessageReceiverListener();
redisMessageListenerContainer.addMessageListener(listener, new ChannelTopic(key));
//添加监听之后,程序挂起,等待Redis Listener唤醒
try {
listener.getLatch().tryAcquire(30, TimeUnit.SECONDS);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
redisMessageListenerContainer.removeMessageListener(listener); //取消redis listener
String response = redisTemplate.opsForValue().get(key);