Springboot 集成 MQTT —— web 服务端实现(apollo 客户端)

基于 MQTT 可以实现很多场景,例如现在使用比较多的物联网,还有消息的实时推送。联网的设备连接上 apollo 服务器以后,一直监听 apollo 推送过来的信令/消息即可。
在这里插入图片描述

1、web 服务端向联网的设备推送信令/消息,上述截图的流程(1.1-1.2)。

1.1、web 服务端向 apollo 服务器发送信令/消息。
1.2、联网的设备通过订阅的主题,收到 web 服务端推送的信令/消息。

2、联网的设备 1 向联网的设备 2 发送信令/消息,上述截图的流程(2.1-2.4)。

2.1、设备 1 向 apollo 服务器发送接收方为设备 2 的消息/信令。
2.2、设备 2 向 web 服务端发起登录。
2.3、设备 2 在 web 服务端登录成功后,设备 2 与 apollo 服务器建立长连接。
2.4、设备 2 通过订阅的主题,收到设备 1 推送的信令/消息。

现在,整体结构已经比较明显了,接下来就会介绍 web 服务端的实现

基于 MQTT 长连接的 web 端实现

基于《Springboot 集成 MQTT —— 搭建 apollo 服务器(Windows)》 一文中搭建的 apollo 服务器,web 端需要配置 apollo 的连接。
在这里插入图片描述
标记部分的内容如下

# 用户名
mqtt.username=admin
# 密码
mqtt.password=password
mqtt.url=tcp://127.0.0.1:61613
# 生产者客户端 ID
mqtt.send.clientId=mqttSendClient
# 消费者客户端 ID
mqtt.recv.clientId=mqttRecvClient

添加上述配置的时候,应该会发现,有些内容不会自动提示,我们需要手动的将上述配置信息配置到 MQTT 客户端的实例中。新增 MqttConfig 类。

import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
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.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;

@Configuration
public class MqttConfig {
    private static final Logger LOGGER = LoggerFactory.getLogger(MqttConfig.class);

    public static final String CHANNEL_RECV = "recvMsgChannel"; // 订阅消息的信道
    public static final String CHANNEL_SEND = "sendMsgChannel"; // 发布消息的信道
    public static final String TOPIC = "topic";

    @Value("${mqtt.username}")
    private String username;

    @Value("${mqtt.password}")
    private String password;

    @Value("${mqtt.url}")
    private String url;

    @Value("${mqtt.send.clientId}")
    private String senderClientId;

    @Value("${mqtt.recv.clientId}")
    private String recverClientId;


    // MQTT 客户端的连接器哦诶之
    @Bean
    public MqttConnectOptions getMqttConnectOptions() {
        MqttConnectOptions options = new MqttConnectOptions();
        // 是否清空 session。false:服务器会保留客户端的连接记录,true:每次连接服务器都以新身份连接
        options.setCleanSession(true);
        options.setUserName(username); // 连接用户
        options.setPassword(password.toCharArray()); // 连接密码
        options.setServerURIs(url.split(","));  // 连接的服务器 url
        options.setConnectionTimeout(10); // 超时时间(单位:s)
        options.setKeepAliveInterval(20); // 保活心跳(单位:s),此方法没有重连机制
        return options;
    }

    // 构造 MQTT 客户端
    @Bean
    public MqttPahoClientFactory mqttClientFactory() {
        DefaultMqttPahoClientFactory factory = new DefaultMqttPahoClientFactory();
        factory.setConnectionOptions(getMqttConnectOptions());
        return factory;
    }

    // MQTT 生产者客户端
    @Bean
    @ServiceActivator(inputChannel = CHANNEL_SEND)
    public MessageHandler mqttMsgSend() {
        MqttPahoMessageHandler messageHandler = new MqttPahoMessageHandler(senderClientId, mqttClientFactory());
        messageHandler.setAsync(true);
        return messageHandler;
    }

    // MQTT 消息订阅绑定(消费者)
    @Bean
    public MessageProducer mqttMsgRecv() {
        // 可以订阅多个 Topic 的消息
        MqttPahoMessageDrivenChannelAdapter adapter = new MqttPahoMessageDrivenChannelAdapter(
                recverClientId, mqttClientFactory(), TOPIC.split(","));
        adapter.setCompletionTimeout(5000);
        adapter.setConverter(new DefaultPahoMessageConverter());
        adapter.setQos(2);
        adapter.setOutputChannel(mqttInboundChannel()); // 设置订阅通道
        return adapter;
    }

    // MQTT信息通道(消费者)
    @Bean(name = CHANNEL_RECV)
    public MessageChannel mqttInboundChannel() {
        return new DirectChannel();
    }

    // MQTT消息处理器(消费者,用于服务端自发自收的测试)
    @Bean
    @ServiceActivator(inputChannel = CHANNEL_RECV)
    public MessageHandler handler() {
        return new MessageHandler() {
            @Override
            public void handleMessage(Message<?> message) throws MessagingException {
                LOGGER.error("msg:{}", message.getPayload());
            }
        };
    }
}

新增一个消息发送接口 IMqttSender

import com.hosh.tech.config.MqttConfig;
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生产者消息发送接口
 * MessagingGateway要指定生产者的通道名称
 */
@Component
@MessagingGateway(defaultRequestChannel = MqttConfig.CHANNEL_SEND)
public interface IMqttSender {

    /**
     * 发送信息到MQTT服务器(实现发送全用户消息)
     * @param data 消息内容
     */
    void sendToMqtt(String data);

    /**
     * 发送信息到 MQTT 服务器(实现发送公告类消息——P2M)
     * @param topic 主题
     * @param payload 消息内容
     */
    void sendToMqtt(@Header(MqttHeaders.TOPIC) String topic,
                    String payload);

    /**
     * 发送信息到 MQTT 服务器(实现发送点对点的消息)
     * @param topic 主题
     * @param qos 对消息处理的几种机制
     * 0 表示的是订阅者没收到消息不会再次发送,消息会丢失
     * 1 表示的是会尝试重试,一直到接收到消息,但这种情况可能导致订阅者收到多次重复消息
     * 2 多了一次去重的动作,确保订阅者收到的消息有一次
     * @param payload 消息内容
     */
    void sendToMqtt(@Header(MqttHeaders.TOPIC) String topic,
                    @Header(MqttHeaders.QOS) int qos,
                    String payload);
}

测试 web 服务端的推送

web 服务端的发送消息的实现
在这里插入图片描述
为了方便测试,消息为自发自收,收消息的实现已经在 MqttConfig 中给出
在这里插入图片描述
通过 http 请求触发自发自收的过程,可以看到如下的打印信息
在这里插入图片描述

发布了34 篇原创文章 · 获赞 34 · 访问量 6万+

猜你喜欢

转载自blog.csdn.net/qq_19154605/article/details/105331118