Springboot集成mqtt

本文介绍了如何在SpringBoot项目中集成MQTTX和EMQX,包括配置MqttProperties,MqttConfiguration,自定义MqttEvent以及使用MqttBox发送和接收消息。还展示了两种消息监听方式:直接订阅和统一监听接口的应用。
摘要由CSDN通过智能技术生成

调试工具:MQTTX+EMQX

前置依赖:

  <!--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>

1. 编写基础配置信息

@ConfigurationProperties("spring.mqtt")
@Component
public class MqttProperties {
    private String username;
    private String password;
    private String hostUrl;
    private String clientId;
    private String receiveTopic;
    private Integer receiveQos = 0;
    private String sendTopic = "demo/test";
    private Integer sendQos = 0;
    private String completionTimeout;
    private Integer keepAlive;
}

2. 编写配置类

@Configuration
@Slf4j
public class MqttConfiguration {

    @Resource
    private MqttProperties mqttProperties;
    /**
     * 事件触发
     */
    @Resource
    private ApplicationEventPublisher eventPublisher;

    public MqttConnectOptions getMqttConnectOptions(){
        MqttConnectOptions mqttConnectOptions=new MqttConnectOptions();
        if(StringUtils.hasText(mqttProperties.getUsername())){
            mqttConnectOptions.setUserName(mqttProperties.getUsername());
        }
        if(StringUtils.hasText(mqttProperties.getPassword())) {
            mqttConnectOptions.setPassword(mqttProperties.getPassword().toCharArray());
        }
        mqttConnectOptions.setServerURIs(mqttProperties.getHostUrl().split(","));
        mqttConnectOptions.setKeepAliveInterval(60);
        //mqttConnectOptions.setMqttVersion(MqttConnectOptions.MQTT_VERSION_3_1);
        mqttConnectOptions.setKeepAliveInterval(mqttProperties.getKeepAlive());
        mqttConnectOptions.setAutomaticReconnect(true);  //重连
        return mqttConnectOptions;
    }


    @Bean
    public MqttPahoClientFactory mqttClientFactory() {

        DefaultMqttPahoClientFactory factory = new DefaultMqttPahoClientFactory();
        factory.setConnectionOptions(this.getMqttConnectOptions());
        return factory;
    }

    @Bean
    public MessageChannel mqttInputChannel() {
        return new DirectChannel();
    }

    /**
     * 配置client,监听入栈消息 topic
     */
    @Bean
    public MessageProducer inbound() {
        MqttPahoMessageDrivenChannelAdapter adapter =
            new MqttPahoMessageDrivenChannelAdapter(mqttProperties.getClientId()+"_inbound", mqttClientFactory(),
                mqttProperties.getReceiveTopic().split(","));
        adapter.setCompletionTimeout(Long.valueOf(mqttProperties.getCompletionTimeout()));
        adapter.setConverter(new DefaultPahoMessageConverter());
        //默认topic
        adapter.addTopic("dsmp/test");
        adapter.setQos(mqttProperties.getReceiveQos());
        adapter.setOutputChannel(mqttInputChannel());
        return adapter;
    }

    @Bean
    @ServiceActivator(inputChannel = "mqttInputChannel")
    public MessageHandler handler() {
        return new MessageHandler() {
            @Override
            public void handleMessage(Message<?> message) throws MessagingException {
                String topic = message.getHeaders().get(MqttHeaders.RECEIVED_TOPIC).toString();
                String qos = message.getHeaders().get(MqttHeaders.RECEIVED_QOS).toString();
                eventPublisher.publishEvent(new MqttEvent(this, topic, message.getPayload().toString()));
            }
        };
    }

    /**
     * 发送消息和消费消息Channel可以使用相同MqttPahoClientFactory
     *
     * @return
     */
    @Bean
    @ServiceActivator(inputChannel = "mqttOutboundChannel")
    public MessageHandler mqttOutbound() {
        // 在这里进行mqttOutboundChannel的相关设置
        MqttPahoMessageHandler messageHandler =  new MqttPahoMessageHandler(mqttProperties.getClientId(), mqttClientFactory());
        // 如果设置成true,发送消息时将不会阻塞。
        messageHandler.setAsync(true);
        messageHandler.setDefaultQos(mqttProperties.getSendQos());
        messageHandler.setDefaultTopic(mqttProperties.getSendTopic());
        return messageHandler;
    }

    @Bean
    public MessageChannel mqttOutboundChannel() {
        return new DirectChannel();
    }
}

3. 自定义事件

/**
 * 自定义mqtt事件
 */
public class MqttEvent extends ApplicationEvent {

    private String topic;
    /**
     * 发送的消息
     */
    private String message;

    public MqttEvent(Object source,String topic,String message) {
        super(source);
        this.topic = topic;
        this.message = message;
    }

    public String getTopic() {
        return topic;
    }

    public void setTopic(String topic) {
        this.topic = topic;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }
}

4. 消息网关

@Component
@MessagingGateway(defaultRequestChannel = "mqttOutboundChannel")
public interface MqttBox {
    void sendToMqtt(String data);

    void sendToMqtt(@Header(MqttHeaders.TOPIC) String topic, String payload);

    void sendToMqtt(@Header(MqttHeaders.TOPIC) String topic, @Header(MqttHeaders.QOS) int qos, String payload);
}

5. 使用

5.1 yml配置:
spring:
  mqtt:
    username:
    password:
    host-url: tcp://127.0.0.1:1884
    client-id: test-demo
    receive-qos: 0
    receive-topic: test1
    send-topic: test2
    send-qos: 1
    completionTimeout: 3000
    keepAlive: 6
5.2.1 直接订阅
@Component
@Slf4j
public class MqttListener {

        @EventListener(condition = "#mqttEvent.topic.startsWith('test')")
        public void onEmqttCalll1(MqttEvent mqttEvent) throws Exception {
            String topic = mqttEvent.getTopic();
            //写逻辑处理
            Log.info("接收到消test:" + mqttEvent.getMessage());
        }

        @EventListener(condition = "#mqttEvent.topic.equals('abc')")
        public void onEmqttCalll2(MqttEvent mqttEvent) throws Exception {
            String topic = mqttEvent.getTopic();
            //写逻辑处理
            Log.info("接收到消abc:" + mqttEvent.getMessage());
        }
}
5.2.1 统一监听 
public interface ITopicHandle {

    /**
     * 判断topic
     *
     * @param topic topic
     * @return
     */
    boolean topicName(String topic);

    /**
     * 处理消息
     *
     * @param msg msg
     */
    void handleMsg(String msg);
}
@Component
@Slf4j
@RequiredArgsConstructor
public class TestTopicHandleImpl implements ITopicHandle {

    private final MqttBox mqttBox;

    @Override
    public boolean topicName(String topic) {
        return topic.equals(CommonConstant.TEST_TOPIC);
    }

    @Override
    public void handleMsg(String msg) {
        log.info("【订阅topic】 | topic:{} | 消息内容msg:{}",         CommonConstant.TEST_TOPIC, msg);

        //
    }
}
 
 
/**
 * @Author qiuzh
 * @Description 订阅主题消息
 * @Date 2023/11/2 9:16
 */
@Component
@Slf4j
@RequiredArgsConstructor
public class MqttListener {

    private final List<ITopicHandle> topicHandle;

    @EventListener
    public void topic(MqttEvent mqttEvent) {
        this.topicHandle.stream()
                .filter(provider -> provider.topicName(mqttEvent.getTopic()))
                .findFirst()
                .ifPresent(provider -> {
                    provider.handleMsg(mqttEvent.getMessage());
                });
    }
}

  • 16
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Qzhangww

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值