ContiNew
消息

MQTT

基于 Spring Integration MQTT 与 Eclipse Paho 封装,提供开箱即用的生产者与消费者能力,支持注解订阅(@MqttListener)与动态订阅(MqttOptions)。

continew-starter-messaging-mqtt 基于 Spring Integration MQTT 与 Eclipse Paho 封装,提供开箱即用的生产者与消费者能力,同时支持注解订阅(@MqttListener)与动态订阅(MqttOptions)。

引入依赖

<dependency>
    <groupId>top.continew.starter</groupId>
    <artifactId>continew-starter-messaging-mqtt</artifactId>
</dependency>

模块会传递引入 spring-integration-mqtt 与 org.eclipse.paho.client.mqttv3。

与多数模块不同,MQTT 的 enabled 默认值为 false(自动配置以 @ConditionalOnProperty(havingValue = "true") 生效),必须显式设置 continew-starter.messaging.mqtt.enabled: true 才会启用。

配置

配置项位于 continew-starter.messaging.mqtt 前缀下,完整定义见 top.continew.starter.messaging.mqtt.autoconfigure.properties.MqttProperties 及嵌套的 MqttProducerProperties、MqttConsumerProperties、MqttWillProperties、MqttExecutorProperties:

配置项说明默认值
enabled是否启用 MQTT 功能false
hostBroker 地址,格式如 tcp://127.0.0.1:1883(支持 tcp / ssl / ws)无(必填)
username用户名无
password密码无
keep-alive-interval心跳间隔(秒)60
max-inflight客户端允许同时存在的最大未确认消息数,超出后新消息阻塞10
clean-session是否清除会话(false = 持久会话,保留订阅与未送达消息)false
connection-timeout连接超时(秒)30
automatic-reconnect是否启用自动重连true
max-reconnect-delay自动重连最大延迟(毫秒)128000
executor-service-timeout关闭执行服务时的等待时长(秒)1
will.topic遗嘱消息主题(客户端异常掉线时由 Broker 发布)无
will.payload遗嘱消息内容无
will.qos遗嘱消息 QoS0
will.retained遗嘱是否为保留消息false
https-hostname-verification-enabled是否启用 HTTPS 主机名验证(SSL/TLS 时)false
ssl-hostname-verifier自定义 HostnameVerifier(替换默认主机名校验策略)无
ssl-client-propsSSL 客户端属性(证书路径、密钥密码等,Map 结构)无
custom-web-socket-headers使用 WebSocket 协议连接时的自定义请求头无
producer.client-id生产者客户端 ID(为空时自动生成:应用名 + UUID)无
producer.default-qos默认 QoS(0/1/2)0
producer.default-topic默认主题(sendToMqtt(payload) 单参方法使用)producer
producer.async是否异步发送false
producer.async-events是否异步触发发送事件(仅 async = true 时生效)false
producer.default-retained是否默认发送保留消息false
producer.executor.*生产者线程池(异步时生效):core-pool-size / max-pool-size / keep-alive-seconds / queue-capacity5 / 10 / 60 / 512
consumer.client-id消费者客户端 ID(为空时自动生成)无
consumer.qos默认订阅 QoS(0/1/2)0
consumer.auto-start-up是否随应用启动自动连接并订阅true
consumer.async是否异步消费(true 时使用线程池处理消息)false
consumer.completion-timeout消息完成等待超时(毫秒)30000(Paho 默认值)
consumer.disconnect-completion-timeout断开连接完成等待超时(毫秒)Paho 默认值
consumer.executor.*消费者线程池(异步时生效),同 producer.executor.*5 / 10 / 60 / 512
continew-starter:
  messaging:
    mqtt:
      enabled: true                     # 必须显式开启
      host: tcp://127.0.0.1:1883        # Broker 地址
      username: ContiNew
      password: ContiNew
      keep-alive-interval: 60
      clean-session: false              # 持久会话
      automatic-reconnect: true
      max-reconnect-delay: 128000
      connection-timeout: 30
      will:                             # 遗嘱消息(可选)
        topic: client/offline
        payload: offline
        qos: 1
        retained: true
      producer:                         # 生产者
        client-id: mqtt-producer-001
        default-qos: 0
        default-topic: default/topic
        async: false
        default-retained: false
      consumer:                         # 消费者
        client-id: mqtt-consumer-001
        qos: 0
        auto-start-up: true
        async: true                     # 异步消费,配合线程池
        executor:
          core-pool-size: 8
          max-pool-size: 16
          queue-capacity: 512

使用示例

注解订阅

实现 MqttMessageConsumer 接口并标注 @MqttListener(该注解本身带有 @Component,无需再标注其他 Spring 注解);topic 支持配置占位符与通配符(+ 单级、# 多级且只能用于末尾),qos 默认 "0":

@Slf4j
@MqttListener(topic = "${robot.mqtt.topic}")
public class RobotMqttConsumer implements MqttMessageConsumer {

    @Override
    public void onMessage(MqttMessage message) {
        log.info("收到消息 - Topic: {}, QoS: {}", message.getTopic(), message.getQos());
        log.info("消息内容: {}", message.getPayload());
    }
}

动态订阅

注入 MqttOptions 在运行时增删订阅主题:

@Component
@RequiredArgsConstructor
public class SubscriptionManager implements ApplicationRunner {

    private final MqttOptions mqttOptions;

    @Override
    public void run(ApplicationArguments args) {
        // 批量添加(默认 QoS),也可 addTopics(1, "a", "b") 指定 QoS
        mqttOptions.addTopics("robot/topic2", "other/topic");
        // 取消订阅:mqttOptions.removeTopics("other/topic");
        // 查询已订阅:mqttOptions.listTopics();
    }
}

发布消息

注入 MqttMessageProducer 网关接口发布消息:

@RestController
@RequiredArgsConstructor
public class MqttController {

    private final MqttMessageProducer producer;

    @PostMapping("/publish")
    public String publish(String payload) {
        // 发送到默认主题(producer.default-topic)
        producer.sendToMqtt(payload);
        // 发送到指定主题
        producer.sendToMqtt("robot/data", payload);
        // 指定主题、QoS 与是否保留消息(payload 也支持 byte[])
        producer.sendToMqtt("robot/data", 1, false, payload);
        return "发送成功";
    }
}

注意事项

  • 消息分发逻辑:消息到达时由 MqttMessageInboundHandler 分发,优先匹配精确的注解订阅,不匹配时检查是否在动态订阅列表中,支持通配符与共享订阅;单个监听器异常会被自动捕获,不影响其他监听器。
  • QoS 选择:0 最多一次(最快,可能丢失)、1 至少一次(可能重复)、2 恰好一次(最可靠)。
  • 消息积压:调大消费者线程池(consumer.executor.core-pool-size / max-pool-size / queue-capacity)并开启 consumer.async。
  • 消息持久化:clean-session: false 配合 producer.default-retained: true,可让离线订阅者在重连后收到未送达消息、新订阅者立即收到保留消息。
  • 注解 vs 动态订阅:注解适合固定主题、写法简洁;动态订阅适合运行时灵活调整,二者可混合使用。

目录