SpringBoot 整合 MQTT
MQTT 消息生产者
创建 maven 项目 provider9001
依赖、配置文件以及主启动类
首先引入 MQTT 相关依赖
<!--mqtt相关依赖-->
<dependency>
<groupId>org.eclipse.paho</groupId>
<artifactId>org.eclipse.paho.client.mqttv3</artifactId>
<version>1.2.5</version>
</dependency>
在配置文件中定义 MQTT 客户端的基本配置
spring:
application:
name: provider
#MQTT配置信息
mqtt:
#MQTT服务端地址,端口默认为11883,如果有多个,用逗号隔开
url: tcp://<Your_MQTT-SERVER_IP>:11883
#用户名
username: admin
#密码
password: public
#客户端id(不能重复)
client:
id: provider_id
#MQTT默认的消息推送主题,实际可在调用接口时指定
default:
topic: test
server:
port: 9001
配置项目主启动类
@SpringBootApplication
public class Provider9001 {
public static void main(String[] args) {
SpringApplication.run(Provider9001.class);
}
}
MQTT 生产者客户端
编写 MQTT 客户端,进行客户端的初始化以及与服务器的连接,编写推送消息的方法
@Component
public class MqttProviderClient {
@Value("${spring.mqtt.username}")
private String username;
@Value("${spring.mqtt.password}")
private String password;
@Value("${spring.mqtt.url}")
private String hostUrl;
@Value("${spring.mqtt.client.id}")
private String clientId;
@Value("${spring.mqtt.default.topic}")
private String defaultTopic;
private MqttClient mqttClient;
/**
* 初始化生产者客户端
*/
@PostConstruct
public void init() {
connect();
}
/**
* 客户端连接服务端
*/
public void connect(){
try {
// 初始化客户端
mqttClient = new MqttClient(hostUrl, clientId, new MemoryPersistence());
// 配置客户端连接参数
MqttConnectOptions options = new MqttConnectOptions();
//是否清空session,设置false表示服务器会保留客户端的连接记录(订阅主题,qos),客户端重连之后能获取到服务器在客户端断开连接期间推送的消息
//设置为true表示每次连接服务器都是以新的身份
options.setCleanSession(true);
// 配置用户名和密码
options.setUserName(username);
options.setPassword(password.toCharArray());
// 设置超时时间,单位为秒
options.setConnectionTimeout(100);
// 设置心跳时间 单位为秒,表示服务器每隔 1.5*20秒的时间向客户端发送心跳判断客户端是否在线
options.setKeepAliveInterval(20);
// 设置遗嘱消息的话题,若客户端和服务器之间的连接意外断开,服务器将发布客户端的遗嘱信息
options.setWill("willTopic", (clientId + "与服务器断开连接").getBytes(), 0, false);
// 配置回调
mqttClient.setCallback(new MqttProviderCallback());
// 执行连接
mqttClient.connect(options);
} catch (MqttException e) {
e.printStackTrace();
}
}
/**
* 客户端消息发送
* @param qos qos
* @param retained retained
* @param topic topic
* @param message message
*/
public void publish(int qos,boolean retained,String topic,String message){
MqttMessage mqttMessage = new MqttMessage();
mqttMessage.setQos(qos);
mqttMessage.setRetained(retained);
mqttMessage.setPayload(message.getBytes());
// 主题的目的地,用于发布/订阅信息
MqttTopic mqttTopic = mqttClient.getTopic(topic);
// 提供一种机制来跟踪消息的传递进度
// 用于在以非阻塞方式(在后台运行)执行发布是跟踪消息的传递进度
MqttDeliveryToken token;
try {
// 将指定消息发布到主题,但不等待消息传递完成,返回的token可用于跟踪消息的传递状态
// 一旦此方法干净地返回,消息就已被客户端接受发布,当连接可用,将在后台完成消息传递
token = mqttTopic.publish(mqttMessage);
token.waitForCompletion();
} catch (MqttException e) {
e.printStackTrace();
}
}
}
MQTT 生产者客户端回调类
配置各种情况下客户端的处理逻辑
@Slf4j
@Component
public class MqttProviderCallback implements MqttCallback {
@Value("${spring.mqtt.client.id}")
private String clientId;
/**
* 断开连接回调
*/
@Override
public void connectionLost(Throwable throwable) {
log.error(clientId + "与服务器断开连接...");
}
/**
* 消息送达回调
*/
@Override
public void messageArrived(String s, MqttMessage mqttMessage) throws Exception {
log.info("信息已送达...");
}
/**
* 发送成功回调
*/
@Override
public void deliveryComplete(IMqttDeliveryToken iMqttDeliveryToken) {
IMqttAsyncClient client = iMqttDeliveryToken.getClient();
log.info(client.getClientId() + "发布消息成功...");
}
}
控制类
@RestController
@RequestMapping("/mqtt/provider")
public class MqttProviderController {
@Resource
MqttProviderClient mqttProviderClient;
/**
* 发送消息
* @param qos qos
* @param retained retained
* @param topic topic
* @param message message
* @return 发送结果
*/
@GetMapping("/sendMessage")
public String sendMessage(int qos, boolean retained, String topic, String message){
try {
mqttProviderClient.publish(qos, retained, topic, message);
return "发送成功";
} catch (Exception e) {
e.printStackTrace();
return "发送失败";
}
}
}
MQTT 消息消费者
创建 maven 项目 consumer9002
依赖、配置文件以及主启动类
依赖同生产者,配置文件修改如下
spring:
application:
name: consumer
#MQTT配置信息
mqtt:
#MQTT服务端地址,端口默认为11883,如果有多个,用逗号隔开
url: tcp://<Your_MQTT-SERVER_IP>:11883
#用户名
username: admin
#密码
password: public
#客户端id(不能重复)
client:
id: consumer_id
#MQTT默认的消息推送主题,实际可在调用接口时指定
default:
topic: test
server:
port: 9002
MQTT 消费者客户端
进行客户端的初始化以及与服务器的连接,并配置订阅的主题以及 QoS
@Component
public class MqttConsumerClient {
@Value("${spring.mqtt.username}")
private String username;
@Value("${spring.mqtt.password}")
private String password;
@Value("${spring.mqtt.url}")
private String hostUrl;
@Value("${spring.mqtt.client.id}")
private String clientId;
@Value("${spring.mqtt.default.topic}")
private String defaultTopic;
/**
* mqtt 客户端
*/
private MqttClient mqttClient;
/**
* 初始化客户端
*/
@PostConstruct
public void init() {
// 初始化逻辑
connect();
}
/**
* 初始化客户端连接服务器
*/
public void connect() {
try {
// 创建服务器连接
mqttClient = new MqttClient(hostUrl, clientId, new MemoryPersistence());
// 配置连接参数
MqttConnectOptions options = new MqttConnectOptions();
// 是否清空session,设置为false表示服务器会保留客户端的连接记录,客户端重连之后能获取到服务器在客户端断开连接期间推送的消息
// 设置为true表示每次连接到服务端都是以新的身份
options.setCleanSession(true);
// 配置用户名和密码
options.setUserName(username);
options.setPassword(password.toCharArray());
// 设置超时时间,单位为秒
options.setConnectionTimeout(100);
// 设置心跳时间 单位为秒,表示服务器每隔1.5*20秒的时间向客户端发送心跳判断客户端是否在线
options.setKeepAliveInterval(20);
// 设置遗嘱消息的话题,若客户端和服务器之间的连接意外断开,服务器将发布客户端的遗嘱信息
options.setWill("willTopic", (clientId + "与服务器断开连接").getBytes(), 0, false);
// 设置回调
mqttClient.setCallback(new MqttConsumerCallback());
// 执行连接
mqttClient.connect(options);
// 配置订阅主题
int[] qos = {1, 1, 1};
String[] topics = {"test", "test1", "test2"};
// 执行订阅
mqttClient.subscribe(topics, qos);
} catch (MqttException e) {
e.printStackTrace();
}
}
/**
* 服务端断开连接
*/
public void disConnect() {
try {
mqttClient.disconnect();
} catch (MqttException e) {
e.printStackTrace();
}
}
}
MQTT 消费者客户端回调类
配置各种情况的回调处理逻辑
@Slf4j
@Component
public class MqttConsumerCallback implements MqttCallback {
@Value("${spring.mqtt.client.id}")
private String clientId;
/**
* 断开连接回调
*/
@Override
public void connectionLost(Throwable throwable) {
log.error(clientId + "与服务器断开连接...");
}
/**
* 监听消息回调
*/
@Override
public void messageArrived(String topic, MqttMessage mqttMessage) throws Exception {
log.info("接收消息主题:{}", topic);
log.info("接收消息Qos:{}", mqttMessage.getQos());
log.info("接收消息内容:{}", new String(mqttMessage.getPayload()));
log.info("接收消息retained:{}", mqttMessage.isRetained());
}
/**
* 发送消息完成回调
*/
@Override
public void deliveryComplete(IMqttDeliveryToken iMqttDeliveryToken) {
}
}
控制类
@RestController
@RequestMapping("/mqtt/consumer")
public class MqttConsumerController {
@Resource
private MqttConsumerClient mqttConsumerClient;
@Value("${spring.mqtt.client.id}")
private String clientId;
@RequestMapping("/connect")
public String connect(){
mqttConsumerClient.connect();
return clientId + "连接到服务器";
}
@RequestMapping("/disConnect")
public String disConnect(){
mqttConsumerClient.disConnect();
return clientId + "与服务器断开连接";
}
}
MQTT 测试使用
启动 EMQX 服务器,登录 dashboard(端口号 18083,初始账号密码见配置文件)
分别启动 MQTT 生产者客户端和消费者客户端,查看 dashboard 是否成功连接至服务器
调用生产者发送消息接口,发送消息
查看消费者监听窗口,获取消息