基于MQTT协议在物联网系统中数据交互的重要角色,入门java项目中mqtt初始化连接与订阅、发布
MQTT服务端broker搭建可移步小生博文:
此演示选用mqtt库:org.eclipse.paho
<!-- https://mvnrepository.com/artifact/org.eclipse.paho/org.eclipse.paho.client.mqttv3 -->
<dependency>
<groupId>org.eclipse.paho</groupId>
<artifactId>org.eclipse.paho.client.mqttv3</artifactId>
<version>1.1.1</version>
</dependency>
将一些固定配置抽取在配置文件:mqtt.properties
#******************mqtt conf info list**************
#mqtt
mqtt.username=yourname
mqtt.password=yourpwd
#mqtt clienid
mqtt.clientid.subscribe=mc_broker_java@@@listener_test
mqtt.clientid.publish=mc_broker_java@@@publisher_test
#mqtt tcp
mqtt.tcp.host=tcp://mqtt.example.cn:1883
#mqtt ssl
mqtt.ssl.host=ssl://mqtt.example.cn:8883
mqtt.ssl.cafile=/Users/chao/Desktop/longSSL/myca_lts.crt
mqtt.ssl.certfile=/Users/chao/Desktop/longSSL/java_lts.crt
mqtt.ssl.keyfile=/Users/chao/Desktop/longSSL/java_lts.pem
mqtt.ssl.keypw=
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.mcrazy.main;
import java.io.File;
import com.mcrazy.tool.PropertyUtil;
import org.eclipse.paho.client.mqttv3.*;
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
import com.mcrazy.tool.Constant;
import com.mcrazy.log.Log;
/**
* MQTT 数据处理插件
* @author chao
* @createDate 2017.1.23
*/
public class McListener {
private String file_conf = "mqtt.properties";
private MqttClient client_sub;
private MqttConnectOptions options_sub;
private String topic_dev = "/examle/data/#";
private String topic_online = "/examle/online/#";
private String topic_will = "/examle/will/#";
private static final McListener listener = new McListener();
public static McListener getInstance() {
return listener;
}
private McListener() {
}
private void initMQTTListener() {
try {
//获取配置信息
StringBuilder builder = new StringBuilder();
String filepath = builder.append(Constant.PATH_CONF).append(File.separator)
.append(file_conf).toString();
PropertyUtil mqttProperty = new PropertyUtil(filepath);
mqttProperty.read();
// HOST_MQ为主机名,clientid即连接MQTT的客户端ID,一般以唯一标识符表示,MemoryPersistence设置clientid的保存形式,默认为以内存保存
client_sub = new MqttClient(mqttProperty.get("mqtt.tcp.host").trim(), mqttProperty.get("mqtt.clientid.subscribe").trim(), new MemoryPersistence());
// MQTT的连接设置
options_sub = new MqttConnectOptions();
// 设置是否清空session,这里如果设置为false表示服务器会保留客户端的连接记录,设置为true表示每次连接到服务器都以新的身份连接
options_sub.setCleanSession(false);
// 设置连接的用户名
options_sub.setUserName(mqttProperty.get("mqtt.username").trim());
// 设置连接的密码
options_sub.setPassword(mqttProperty.get("mqtt.password").trim().toCharArray());
// 设置会话心跳时间 单位为秒 服务器会每隔90秒的时间向客户端发送个消息判断客户端是否在线,但这个方法并没有重连的机制
options_sub.setKeepAliveInterval(90);
//订阅topic定义
int[] Qos = new int[]{0, 0, 0};
String[] topics = new String[]{topic_online, topic_will, topic_dev};
// 设置回调
client_sub.setCallback(new MqttCallbackExtended() {
public void connectComplete(boolean reconnect, String serverURI) {
//连接成功,需要上传客户端所有的订阅关系
try {
client_sub.subscribe(topics, Qos);
Log.err.info("=======连接MQTT HOST 成功,重发Topics 1{}=2{}=3{}=======", topic_online, topic_will, topic_dev);
} catch (Exception e) {
Log.err.info("=======重连MQTT HOST 失败: {}, case: {}=========", serverURI, e.toString());
}
}
public void connectionLost(Throwable cause) {
// 连接丢失后,一般在这里面进行重连
Log.err.info("=======连接断开,可以做重连==============");
// reConnect();
}
public void deliveryComplete(IMqttDeliveryToken token) {
Log.err.info("=======交付完成: {}==============", token.isComplete());
}
public void messageArrived(String topic, MqttMessage message) {
//due arrived message...
Log.err.info("=======收到消息topic: {}===Qos: {}", topic, message.getQos());
Log.err.info("=======message: {}", message.toString());
}
});
//连接mqtt服务器broker
client_sub.connect(options_sub);
//订阅消息
client_sub.subscribe(topics, Qos);
} catch (Exception e) {
// TODO Auto-generated catch block
Log.err.info("init listener MQTT err info: {}", e.toString());
System.exit(-1);
}
}
/**
* mqtt重连
*/
public void reConnect() {
try {
if (null != client_sub && !(client_sub.isConnected())) {
client_sub.reconnect();
Log.err.info("=======尝试重新连接==============");
}
} catch (MqttException e) {
Log.err.info("=======重新连接失败:{}==============", e.toString());
}
}
public static void main(String[] args) {
// 初始化数据侦听模块
McListener.getInstance().initMQTTListener();
}
}
发布用到方法:publish
源码
public void publish(String topic, MqttMessage message) throws MqttException, MqttPersistenceException {
this.aClient.publish(topic, message, (Object)null, (IMqttActionListener)null).waitForCompletion(this.getTimeToWait());
}
简单使用
package com.mcrazy.manager.publisher;
import com.mcrazy.log.Log;
import com.mcrazy.main.McPublisher;
import org.eclipse.paho.client.mqttv3.MqttMessage;
public class PacketPublisher implements Runnable {
private String topic = "";
private String msg = "";
public PacketPublisher(String topic, String msg) {
this.topic = topic;
this.msg = msg;
}
@Override
public void run() {
MqttMessage msg_pub = new MqttMessage(msg.getBytes());
msg_pub.setQos(0);
Log.err.info("=======准备发送Topic:{}========", topic);
Log.err.info("=======准备发送Message:{}========", msg);
try {
McPublisher.getInstance().getMqttClient().publish(topic, msg_pub);
} catch (Exception e) {
Log.err.info("=======发布主题消息失败:topic: {}=========", topic);
}
}
}