我們現在所使用的通訊硬體大多數都是以UTF-8字元和ASCII的編碼格式進行訊息收發。
MQTT測試工具,請檢視上一篇內容。
一、配置pom的maven依賴
<dependency> <groupId>org.fusesource.hawtbuf</groupId> <artifactId>hawtbuf</artifactId> <version>1.11</version> </dependency> <dependency> <groupId>org.fusesource.hawtdispatch</groupId> <artifactId>hawtdispatch</artifactId> <version>1.22</version> </dependency> <dependency> <groupId>org.fusesource.hawtdispatch</groupId> <artifactId>hawtdispatch-transport</artifactId> <version>1.22</version> </dependency> <dependency> <groupId>org.fusesource.mqtt-client</groupId> <artifactId>mqtt-client</artifactId> <version>1.16</version> </dependency>
為了程式碼的可閱讀性,我將以下程式碼按照功能封裝到不同的類當中。
二、MQTT資料接收類
package com.xxxx.controller.Server.MQTT; import com.xxxx.common.utils.PropertyUtils; import com.xxxx.worker.controller.Server.Execute.MessageExecute; import org.eclipse.paho.client.mqttv3.*; import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; /** * @title: MQTT訊息訂閱(接收字串) * @author: hunttown * @date: 2021年10月17日 9:10 * @description: 當前類用bean注入,不要使用註解注入,因為下面要將其配置到worker裡 */ public class MQTTSubscribe implements MqttCallback { //伺服器地址 private String serverUrl = "你的伺服器IP:埠"; //客戶端唯一標識 private String clientid = "隨便起個名字"; //訂閱主題 private String subtopic = "你的訂閱主題"; //使用者名稱 private String username = "使用者名稱"; //密碼 private String password = "密碼"; //傳輸質量:0至多一次;1至少一次;2確保只有一次。 private int qos = 0; private MqttClient client; private MqttConnectOptions options; private MessageExecute messageExecute = new MessageExecute(); //斷線重連,每10秒檢測一次 void startReconnect() { ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor(); scheduler.scheduleAtFixedRate(new Runnable() { public void run() { if (!client.isConnected()) { try { client.connect(options); System.out.println("我已斷線重連......"); } catch (MqttException e) { e.printStackTrace(); } } } }, 3 * 1000, 10 * 1000, TimeUnit.MILLISECONDS); } Boolean start() { try { client = new MqttClient(serverUrl, clientid, new MemoryPersistence()); options = new MqttConnectOptions(); options.setCleanSession(false); options.setUserName(username); options.setPassword(password.toCharArray()); options.setConnectionTimeout(10); options.setKeepAliveInterval(20); options.setAutomaticReconnect(true); client.setCallback(this); client.connect(options); client.subscribe(subtopic, qos); System.out.println("MQTT訂閱設定初始化完畢!"); return true; } catch (Exception e) { e.printStackTrace(); System.out.println("MQTT訂閱設定初始化失敗!"); return false; } } public void connectionLost(Throwable cause) { System.out.println("------------ mqtt connection lost. ------------"); } @Override public void deliveryComplete(IMqttDeliveryToken token) { try { System.out.println("------------ delivery complete ------------" + token.isComplete()); } catch (Exception e) { e.printStackTrace(); } } @Override public void messageArrived(String topic, MqttMessage message) throws Exception { String msg = new String(message.getPayload()); System.out.println("------------ 已接收到資訊: ------------" + msg); //這裡開始處理你的業務 //1、如果數量較大,可使用中介軟體暫存資訊,如:MQ //2、如果數量較小,可以使用非同步處理 //TODO } }
三、執行緒類
package com.xxxx.worker.controller.Server.MQTT; /** * @title: 啟動一個執行緒 * @author: hunttown * @date: 2020年10月17日 15:55 * @description: 同樣要使用bean注入 */ public class MQTTStrThread extends Thread { private static MQTTSubscribe mqttSubscribe; public void run() { //訂閱任務是否啟動 boolean isStart = false; while (!isStart) { //啟動,如果執行緒先於伺服器啟動,是讀不到配置檔案的,這裡會報錯,那麼休眠60秒繼續。 isStart = mqttSubscribe.start(); //啟動成功 if (isStart) { mqttSubscribe.startReconnect(); System.out.println("MQTT訂閱任務啟動成功!"); } else { System.out.println("MQTT訂閱任務啟動失敗,1分鐘後繼續重試!"); try { Thread.sleep(60 * 1000); } catch (InterruptedException e) { e.printStackTrace(); } } } } public static MQTTSubscribe getMqttSubscribe() { return mqttSubscribe; } public static void setMqttSubscribe(MQTTSubscribe mqttSubscribe) { MQTTStrThread.mqttSubscribe = mqttSubscribe; } }
四、監聽類
package com.xxxx.worker.controller.TaskListener; import com.xxxx.worker.controller.Server.MQTT.MQTTStrThread; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; import javax.servlet.http.HttpServlet; /** * @title: MQTT訊息監聽類 * @author: wangjunfu * @date: 2020年10月17日 18:36 * @description: 同樣是bean注入 */ public class MQTTStrListener extends HttpServlet implements ServletContextListener { public void contextInitialized(ServletContextEvent arg0) { System.out.println("----------------- MQTT:String執行緒已啟動 --------------------------"); MQTTStrThread thread = new MQTTStrThread(); thread.setDaemon(true); //設定執行緒為後臺執行緒 thread.start(); } public void contextDestroyed(ServletContextEvent arg0) { // TODO } }
五、將監聽類配置到web.xml中
<listener> <!-- MQTT:接收String資料 --> <listener-class>com.xxxx.worker.controller.TaskListener.MQTTStrListener</listener-class> </listener>
完畢!