SpringBoot 集成mqtt

在Spring Boot中集成MQTT(Message Queuing Telemetry Transport)是一个常见的需求,尤其是在需要实现物联网(IoT)通信时。MQTT是一种轻量级的、基于发布/订阅模式的消息传输协议,广泛用于低带宽、不可靠或高延迟的网络环境中。

以下是一个基本的步骤指南,介绍如何在Spring Boot项目中集成MQTT:

1. 添加依赖

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

2. 配置MQTT客户端

参数配置

@Data
@Component("mqttConfigProp")
@ConfigurationProperties(prefix = "mqtt")
public class MqttConfigProp {
    private String[] serverURIs;
    private String clientId;
    private String userName;
    private char[] password;
    private String topic;
    private int timeout;
    private int keepAlive;
    private boolean cleanSession;
}

接收配置

@Slf4j
@Configuration
@EnableIntegration
public class MqttConfigurationInbound {

    @Autowired
    private MqttConfigProp mqttConfigProp;

    @Bean
    public MqttConnectOptions mqttConnectOptionInbound() {
        MqttConnectOptions options = new MqttConnectOptions();
        options.setServerURIs(mqttConfigProp.getServerURIs());
        options.setUserName(mqttConfigProp.getUserName());
        options.setPassword(mqttConfigProp.getPassword());
        options.setKeepAliveInterval(mqttConfigProp.getKeepAlive());
        options.setCleanSession(mqttConfigProp.isCleanSession());
        return options;
    }
    @Bean
    public MqttPahoClientFactory mqttClientFactoryInbound() {
        DefaultMqttPahoClientFactory factory = new DefaultMqttPahoClientFactory();
        factory.setConnectionOptions(mqttConnectOptionInbound());
        return factory;
    }

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

    @Bean
    public MessageProducer brokerMqttInbound() {
        MqttPahoMessageDrivenChannelAdapter adapter = new MqttPahoMessageDrivenChannelAdapter(
                mqttConfigProp.getClientId()+ UUID.randomUUID().toString() + "_inbound",
                mqttConnectOptionInbound(), mqttConfigProp.getTopic());
        adapter.setConverter(new DefaultPahoMessageConverter());
        adapter.setOutputChannel(mqttInputChannel());
        adapter.setCompletionTimeout(mqttConfigProp.getTimeout());
        adapter.setQos(1);
        return adapter;
    }

    /**
     * mqtt连接失败或者订阅失败事件
     * @param event
     */
    @EventListener(MqttConnectionFailedEvent.class)
    public void mqttConnectionFailedEvent(MqttConnectionFailedEvent event) {
        log.error("mqttConnectionFailedEvent连接mqtt失败: " +
                        "date={}, error={}",
                new Date(), event.getCause().getMessage());
    }

    /**
     * 当async和async事件(async-events)都为true时,将发出MqttMessageSentEvent
     * 它包含消息、主题、客户端库生成的消息id、clientId和clientInstance(每次连接客户端时递增)
     * @param event
     */
    @EventListener(MqttMessageSentEvent.class)
    public void mqttMessageSentEvent(MqttMessageSentEvent event) {
        log.info("mqttMessageSentEvent发送信息: date={}, info={}", new Date(), event.toString());
    }

    /**
     * 当async和async事件(async-events)都为true时,将发出MqttMessageDeliveredEvent
     * 当客户端库确认传递时,将发出MqttMessageDeliveredEvent。它包含messageId、clientId和clientInstance,使传递与发送相关。
     * @param event
     */
    @EventListener(MqttMessageDeliveredEvent.class)
    public void mqttMessageDeliveredEvent(MqttMessageDeliveredEvent event) {
        log.info("mqttMessageDeliveredEvent发送成功信息: date={}, info={}", new Date(), event.toString());
    }

    /**
     * 成功订阅到主题,MqttSubscribedEvent事件就会被触发(多个主题,多次触发)
     * @param event
     */
    @EventListener(MqttSubscribedEvent.class)
    public void mqttSubscribedEvent(MqttSubscribedEvent event) {
        log.info("mqttSubscribedEvent订阅成功信息: date={}, info={}", new Date(), event.toString());
    }


}

输出配置

@Slf4j
@Configuration
@EnableIntegration
public class MqttConfigurationOutBound {

    @Autowired
    private MqttConfigProp mqttConfigProp;

    @Bean
    public MqttConnectOptions mqttConnectOptionsOutBound() {
        MqttConnectOptions options = new MqttConnectOptions();
        options.setServerURIs(mqttConfigProp.getServerURIs());
        options.setUserName(mqttConfigProp.getUserName());
        options.setPassword(mqttConfigProp.getPassword());
        options.setKeepAliveInterval(mqttConfigProp.getKeepAlive());
        options.setCleanSession(mqttConfigProp.isCleanSession());
        return options;
    }
    @Bean
    public MqttPahoClientFactory mqttClientFactoryOutBound() {
        DefaultMqttPahoClientFactory factory = new DefaultMqttPahoClientFactory();
        factory.setConnectionOptions(mqttConnectOptionsOutBound());
        return factory;
    }

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

    @Bean
    public MessageHandler mqttOutbound() {
        MqttPahoMessageHandler messageHandler = new MqttPahoMessageHandler(
                mqttConfigProp.getClientId()+ UUID.randomUUID().toString() + "_outbound", mqttClientFactoryOutBound());
        messageHandler.setAsync(true);
        messageHandler.setCompletionTimeout(mqttConfigProp.getTimeout());
        return messageHandler;
    }

    @Bean
    public IntegrationFlow mqttOutboundFlow() {
        return IntegrationFlows.from(mqttOutputChannel())
                .handle(mqttOutbound())
                .get();
    }


}

消息处理

@Service
@Slf4j
public class MqttHandler implements MessageHandler {

   
    @ServiceActivator(inputChannel = "mqttInputChannel")
    @Override
    public void handleMessage(Message<?> message) throws MessagingException {
        String topic = message.getHeaders().get(MqttHeaders.RECEIVED_TOPIC, String.class);
        log.info("topic:{}",topic);
        Object payload = message.getPayload();
        log.info("message info:{}",payload );       
    }
   
}

发送消息

@Component
@MessagingGateway(defaultRequestChannel = "mqttOutputChannel")
public interface MqttGateway {

    /**
     * 发送信息到MQTT服务器
     *
     * @param topic 主题
     * @param message 消息主体
     */
    @Gateway(replyTimeout = 2, requestTimeout = 200)
    void publishMqttMessageWithTopic(String message, @Header(MqttHeaders.TOPIC) String topic);

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值