spring boot mqtt开发-原生 Paho 手动封装(最高灵活性,完全自定义)

文章目录

Mqtt的java开发,归纳起来包含如下5种方式:

方法类型 封装程度 开发效率 灵活性 企业级特性 适用场景
原生 Paho 手动封装 极高 无(需自研)
Spring Integration MQTT (集成流) 中大型项目、Spring 集成生态
spring-boot-starter-mqtt 极高 小型项目、快速原型开发
cn.herodotus.stirrup 极高 极高 (重连 / 重试 / 连接池) 企业级项目、高可靠需求
emqx-spring-boot-starter 通用企业级项目、EMQ 生态

本文主要是采用第一种,原生方式。原生 Paho 手动封装(最高灵活性,完全自定义)

核心优势

  • 无第三方依赖,仅依赖 Paho 核心包;
  • 完全自定义连接、订阅、回调逻辑,无封装层限制;
  • 资源占用极低,适配嵌入式 / 轻量场景。

废话不多说,看代码,步骤。


一、pom.xml依赖

b 复制代码
<!-- 仅引入 Paho MQTT 核心依赖(无任何封装) -->
<dependency>
    <groupId>org.eclipse.paho</groupId>
    <artifactId>org.eclipse.paho.client.mqttv3</artifactId>
    <version>1.2.5</version>
</dependency>

二、yml文件配置

b 复制代码
mqtt:
  broker: tcp://localhost:1883
  clientId: paho-client-${random.value}
  username: admin
  password: public
  qos: 1

三、配置类

创建配置类,初始化 MQTT 客户端并自动订阅配置的主题,无需手动启动,Spring Boot 启动时自动加载:

b 复制代码
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
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;

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

    // 从配置文件读取参数
    @Value("${mqtt.broker:tcp://localhost:1883}")
    private String broker;
    @Value("${mqtt.clientId:paho-client-${random.value}}")
    private String clientId;
    @Value("${mqtt.username:admin}")
    private String username;
    @Value("${mqtt.password:public}")
    private String password;
    @Value("${mqtt.qos:1}")
    private int qos;

    /**
     * 手动创建 MQTT 客户端(核心)
     */
    @Bean
    public MqttClient mqttClient() {
        try {
            // 1. 创建连接配置
            MqttConnectOptions options = new MqttConnectOptions();
            options.setUserName(username);
            options.setPassword(password.toCharArray());
            options.setCleanSession(true); // 断开后清除会话
            options.setConnectionTimeout(30); // 连接超时
            options.setKeepAliveInterval(60); // 心跳间隔
            options.setAutomaticReconnect(true); // 开启自动重连(Paho 原生特性)

            // 2. 创建客户端(内存持久化,避免文件IO)
            MqttClient client = new MqttClient(broker, clientId, new MemoryPersistence());
            // 3. 设置消息回调(处理收到的消息)
            client.setCallback(new CustomMqttCallback());
            // 4. 连接服务器
            client.connect(options);
            log.info("原生 Paho MQTT 客户端连接成功 → broker: {}", broker);

            // 5. 订阅主题(可订阅多个)
            client.subscribe("sensor/temp", qos);
            client.subscribe("test/paho/#", qos);
            log.info("原生 Paho 订阅主题成功");

            return client;
        } catch (MqttException e) {
            log.error("原生 Paho MQTT 客户端初始化失败", e);
            throw new RuntimeException(e);
        }
    }

    /**
     * 消息发送工具类(封装发布逻辑)
     */
    @Bean
    public MqttMessageSender mqttMessageSender() {
        return new MqttMessageSender(mqttClient(), qos);
    }
}

四、消息处理类

创建消息监听类,重写消息接收方法,所有订阅主题的消息都会走到这里,可根据主题区分处理:

b 复制代码
import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.MqttCallback;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Paho 原生消息回调(必须实现 MqttCallback 接口)
 */
public class CustomMqttCallback implements MqttCallback {
    private static final Logger log = LoggerFactory.getLogger(CustomMqttCallback.class);

    // 收到消息时触发(核心方法)
    @Override
    public void messageArrived(String topic, MqttMessage message) throws Exception {
        String content = new String(message.getPayload(), "UTF-8");
        log.info("原生 Paho 收到消息 → 主题:{},QoS:{},内容:{}",
                topic, message.getQos(), content);
        // 业务逻辑处理...
    }

    // 连接断开时触发(可自定义重连逻辑)
    @Override
    public void connectionLost(Throwable cause) {
        log.error("原生 Paho MQTT 连接断开", cause);
    }

    // 消息发布完成时触发(发布者用)
    @Override
    public void deliveryComplete(IMqttDeliveryToken token) {
        // 空实现(订阅者无需处理)
    }
}

五、消息发送工具类

b 复制代码
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 封装消息发送逻辑
 */
public class MqttMessageSender {
    private static final Logger log = LoggerFactory.getLogger(MqttMessageSender.class);
    private final MqttClient client;
    private final int qos;

    public MqttMessageSender(MqttClient client, int qos) {
        this.client = client;
        this.qos = qos;
    }

    /**
     * 发送 MQTT 消息
     */
    public void send(String topic, String content) {
        try {
            MqttMessage message = new MqttMessage(content.getBytes("UTF-8"));
            message.setQos(qos);
            message.setRetained(false); // 不保留消息
            client.publish(topic, message);
            log.info("原生 Paho 发送消息成功 → 主题:{},内容:{}", topic, content);
        } catch (Exception e) {
            log.error("原生 Paho 发送消息失败", e);
        }
    }
}

六、测试

b 复制代码
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;

@RestController
public class PahoTestController {
    @Resource
    private MqttMessageSender mqttMessageSender;

    @GetMapping("/paho/send")
    public String sendMsg(@RequestParam String topic, @RequestParam String content) {
        mqttMessageSender.send(topic, content);
        return "原生 Paho 消息发送成功!";
    }
}
相关推荐
冰暮流星6 小时前
javascript之数组
java·前端·javascript
Re.不晚6 小时前
JAVA进阶之路——无奖问答挑战3
java·开发语言
不倒翁玩偶7 小时前
IDEA导入新的SpringBoot项目没有启动按钮
java·spring boot·intellij-idea
小小小米粒7 小时前
Maven Tools
java
苏三说技术7 小时前
xxl-job 和 elastic-job,哪个更好?
后端
三小河7 小时前
Agent Skill与Rules的区别——以Cursor为例
前端·javascript·后端
kali-Myon7 小时前
2025春秋杯网络安全联赛冬季赛-day1
java·sql·安全·web安全·ai·php·web
我是咸鱼不闲呀7 小时前
力扣Hot100系列20(Java)——[动态规划]总结(下)( 单词拆分,最大递增子序列,乘积最大子数组 ,分割等和子集,最长有效括号)
java·leetcode·动态规划
三小河7 小时前
前端视角详解 Agent Skill
前端·javascript·后端
清水白石0087 小时前
深入解析 LRU 缓存:从 `@lru_cache` 到手动实现的完整指南
java·python·spring·缓存