文章目录
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 消息发送成功!";
}
}