mqtt的使用与二次封装

前提:先安装Mosquitto并启动服务,可使用mqttx进行接收发送的测试。
Mosquitto以配置启动命令

mosquitto -c mosquitto.conf -v

原文链接:mqtt的使用
本文为测试使用固无账号密码,可在原文查看

封装后实现效果,加入一个新的topic时新建一个类进行自动订阅,该类写所订阅topic方法的处理。发送消息看原文使用方法。

所用依赖

<!--mqtt包-->
        <dependency>
            <groupId>org.springframework.integration</groupId>
            <artifactId>spring-integration-mqtt</artifactId>
            <version>5.5.14</version>
        </dependency>
        <!--gson包-->
        <dependency>
            <groupId>com.google.code.gson</groupId>
            <artifactId>gson</artifactId>
            <version>2.9.0</version>
        </dependency>

配置文件

spring:
  mqtt:
    url: tcp://127.0.0.1:1883
    clientId: mqttx_867916f3
    completionTimeout: 2000

封装后代码,链接mqtt工具类

package Ceshi.configure.mqtt;

import javax.annotation.PostConstruct;

import org.eclipse.paho.client.mqttv3.*;
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;

@Configuration
public class MqttConsumerConfig {

    @Value("${spring.mqtt.url}")
    private String hostUrl;

    @Value("${spring.mqtt.clientId}")
    private String clientId;

    /**
     * 客户端对象
     */
    private MqttClient client;

    /**
     * 在bean初始化后连接到服务器
     */
    @PostConstruct
    public void init(){
        connect();
    }

    /**
     * 客户端连接服务端
     */
    public void connect(){
        try {
            //创建MQTT客户端对象
            client = new MqttClient(hostUrl,clientId,new MemoryPersistence());
            //连接设置
            MqttConnectOptions options = new MqttConnectOptions();
            //是否清空session,设置为false表示服务器会保留客户端的连接记录,客户端重连之后能获取到服务器在客户端断开连接期间推送的消息
            //设置为true表示每次连接到服务端都是以新的身份
            options.setCleanSession(true);
            //设置超时时间,单位为秒
            options.setConnectionTimeout(100);
            //设置心跳时间 单位为秒,表示服务器每隔1.5*20秒的时间向客户端发送心跳判断客户端是否在线
            options.setKeepAliveInterval(20);
            //设置遗嘱消息的话题,若客户端和服务器之间的连接意外断开,服务器将发布客户端的遗嘱信息
            options.setWill("willTopic",(clientId + "与服务器断开连接").getBytes(),0,false);
            //设置回调
            client.setCallback(new MqttConsumerCallBack());
            client.connect(options);
        } catch (MqttException e) {
            e.printStackTrace();
        }
    }

    /**
     * 断开连接
     */
    public void disConnect(){
        try {
            client.disconnect();
        } catch (MqttException e) {
            e.printStackTrace();
        }
    }


    /**
     * 订阅主题
     */
    public void subscribe(String topic,int qos){
        try {
            client.subscribe(topic,qos);
        } catch (MqttException e) {
            e.printStackTrace();
        }
    }
    /**
    * @Description: 消息发布
    */
    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 = client.getTopic(topic);
        //提供一种机制来跟踪消息的传递进度
        //用于在以非阻塞方式(在后台运行)执行发布是跟踪消息的传递进度
        MqttDeliveryToken token;
        try {
            //将指定消息发布到主题,但不等待消息传递完成,返回的token可用于跟踪消息的传递状态
            //一旦此方法干净地返回,消息就已被客户端接受发布,当连接可用,将在后台完成消息传递。
            token = mqttTopic.publish(mqttMessage);
            token.waitForCompletion();
        } catch (MqttException e) {
            e.printStackTrace();
        }
    }
}


监听消息工具类

package Ceshi.configure.mqtt;

import org.eclipse.paho.client.mqttv3.IMqttAsyncClient;
import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.MqttCallback;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.springframework.beans.factory.annotation.Value;

import java.util.HashMap;
import java.util.Map;

public class MqttConsumerCallBack implements MqttCallback{

    @Value("${spring.mqtt.clientId}")
    private String clientId;
    private static Map<String,JIantingChuli> maps=new HashMap<>();
    public static void setJIantingChulis(String k,JIantingChuli y){
        maps.put(k,y);
    }
    /**
     * 客户端断开连接的回调
     */
    @Override
    public void connectionLost(Throwable throwable) {
        System.out.println(clientId+"与服务器断开连接,可重连");
    }

    /**
     * 消息到达的回调
     */
    @Override
    public void messageArrived(String topic, MqttMessage message) throws Exception {
        System.out.println(String.format("接收消息主题 : %s",topic));
        System.out.println(String.format("接收消息Qos : %d",message.getQos()));
        System.out.println(String.format("接收消息内容 : %s",new String(message.getPayload())));
        System.out.println(String.format("接收消息retained : %b",message.isRetained()));
        maps.get(topic).xiaoxifenhua(new String(message.getPayload()));//调用方法进行消费
    }

    /**
     * 消息发布成功的回调
     */
    @Override
    public void deliveryComplete(IMqttDeliveryToken iMqttDeliveryToken) {
        IMqttAsyncClient client = iMqttDeliveryToken.getClient();
        System.out.println(client.getClientId()+"发布消息成功!");
    }

}

统一处理消息接口

public  interface JIantingChuli {
    //根据fname找到要执行的方法,后者为传参
    void xiaoxifenhua(String message);
}

接收报文格式类

import lombok.AllArgsConstructor;
import lombok.Data;

import java.io.Serializable;

@Data
@AllArgsConstructor
public class MqResult implements Serializable{

    private String key;//方法名
    private Object data;//方法所需参数
}

一个测试订阅类(重点)(自己根据需求几个topic复制几个,内部topic与qos看情况修改,xiaoxifenhua内有几个方法就写几个分支,k为方法名)

import Ceshi.configure.mqtt.JIantingChuli;
import Ceshi.configure.mqtt.MqResult;
import Ceshi.configure.mqtt.MqttConsumerCallBack;
import Ceshi.configure.mqtt.MqttConsumerConfig;
import Ceshi.param.AppCodeApiParam;
import com.google.gson.Gson;
import lombok.Data;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;


@Component
public class Ceshi1 implements JIantingChuli {
    @Resource
    private MqttConsumerConfig mqttConsumerConfig;
    private Gson gson=new Gson();
    private String topic="ceshi";
    private int qos=2;

    @PostConstruct
    public void chushihua(){
        mqttConsumerConfig.subscribe(topic,qos);//添加到订阅
        MqttConsumerCallBack.setJIantingChulis(topic,this);//监听到消息时找到此类对象
        System.out.println(topic+","+qos+"已注册订阅");
    }
    @Override
    public void xiaoxifenhua(String message) {
        MqResult mqres=gson.fromJson(message,MqResult.class);//json解析为对象
        switch (mqres.getKey()){
            case "ceshi":
                ceshi(gson.fromJson(mqres.getData().toString(), AppCodeApiParam.class));//AppCodeApiParam是随便一个类,内部有个getPassword方法显示参数值
                break;
        }
    }
    //随便写的测试方法t
    public void ceshi(AppCodeApiParam appCodeApiParam){
        System.out.println(appCodeApiParam.getPassword());
    }
}

QoS0,At most once,至多一次;
QoS1,At least once,至少一次;
QoS2,Exactly once,确保只有一次。
因上方测试类topic=“ceshi”,所以我们用MqttX进行测试一下(试了一下发送时qos等于啥都能接收到,只要topic相等)
在这里插入图片描述
参数(按照参数格式来key是要调用的方法名,data是所传参数)

{
  "key": "ceshi",//方法名
  "data": {//要传的参数
    "password":"132465"
  }
}

启动后可看见已注册订阅
在这里插入图片描述

发送消息测试结果,可见触发的方法与传递的参数均无误
在这里插入图片描述

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

翎墨袅

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值