我们现在所使用的通讯硬件大多数都是以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>
完毕!