• Mqtt的坑,真的坑


    业务需要订阅第三方主题,于是碰见了Mqtt接着就发现了 在 springboot 中整合mqtt 回调方法 messageArrived()获取数据时如果直接操作数据库会使连接断开

    头大,网上查了好久,看了好多哥们的博客,也没记下来都借鉴了哪些的。感谢各位大佬,啥也不说了,贴代码记录一下

    @Slf4j
    public class McListener {



    private MqttClient client_sub;
    private MqttConnectOptions options_sub;
    // 用户名
    private final String username = "****";
    // 密钥
    private final String password = "********";
    // 主题
    private final String footballTopic = "*******";
    // 主题
    private final String basketballTopic = "*******";

    private final String broker = "*******";//你订阅的地址

    private final String clientId = "MqttClient_"+ System.currentTimeMillis();

    private static final McListener listener = new McListener();

    public static McListener getInstance() {
    return listener;
    }

    private McListener() {

    }
    public void initMQTTListener() {
    try {
    //获取配置信息
    // HOST_MQ为主机名,clientid即连接MQTT的客户端ID,一般以唯一标识符表示,MemoryPersistence设置clientid的保存形式,默认为以内存保存
    client_sub = new MqttClient(broker, clientId, new MemoryPersistence());
    // MQTT的连接设置
    options_sub = new MqttConnectOptions();
    // 设置是否清空session,这里如果设置为false表示服务器会保留客户端的连接记录,设置为true表示每次连接到服务器都以新的身份连接
    options_sub.setCleanSession(false);
    // 设置连接的用户名
    options_sub.setUserName(username);
    // 设置连接的密码
    options_sub.setPassword(password.toCharArray());
    // 设置会话心跳时间 单位为秒 服务器会每隔90秒的时间向客户端发送个消息判断客户端是否在线,但这个方法并没有重连的机制
    options_sub.setKeepAliveInterval(90);
    //订阅topic定义
    int[] Qos = new int[]{0, 0};
    String[] topics = new String[]{footballTopic, basketballTopic};

    // 设置回调
    client_sub.setCallback(new PushCallback());
    //连接mqtt服务器broker
    client_sub.connect(options_sub);
    //订阅消息
    client_sub.subscribe(topics, Qos);
    } catch (Exception e) {
    // TODO Auto-generated catch block
    log.error("init listener MQTT err info: {}", e.toString());
    System.exit(-1);
    }
    }
    public void reConnect() {
    try {
    if (null != client_sub && !(client_sub.isConnected())) {
    client_sub.reconnect();
    log.error("=======尝试重新连接==============");
    }
    } catch (MqttException e) {
    log.error("=======重新连接失败:{}==============", e.toString());
    }
    }
    /**
    * 向某个主题发布消息 默认qos:1
    *
    * @param topic:发布的主题
    * @param msg:发布的消息
    */
    public void pub(String topic, String msg) throws MqttException {
    MqttMessage mqttMessage = new MqttMessage();
    //mqttMessage.setQos(2);
    mqttMessage.setPayload(msg.getBytes());
    MqttTopic mqttTopic = client_sub.getTopic(topic);
    MqttDeliveryToken token = mqttTopic.publish(mqttMessage);
    token.waitForCompletion();
    }

    /**
    * 向某个主题发布消息
    *
    * @param topic: 发布的主题
    * @param msg: 发布的消息
    * @param qos: 消息质量 Qos:0、1、2
    */
    public void pub(String topic, String msg, int qos) throws MqttException {
    MqttMessage mqttMessage = new MqttMessage();
    mqttMessage.setQos(qos);
    mqttMessage.setPayload(msg.getBytes());
    MqttTopic mqttTopic = client_sub.getTopic(topic);
    MqttDeliveryToken token = mqttTopic.publish(mqttMessage);
    token.waitForCompletion();
    }

    /**
    * 订阅某一个主题 ,此方法默认的的Qos等级为:1
    *
    * @param topic 主题
    */
    public void sub(String topic) throws MqttException {
    client_sub.subscribe(topic);
    }

    /**
    * 订阅某一个主题,可携带Qos
    *
    * @param topic 所要订阅的主题
    * @param qos 消息质量:0、1、2
    */
    public void sub(String topic, int qos) throws MqttException {
    client_sub.subscribe(topic, qos);
    }
    /**
    * 关闭MQTT连接
    */
    public void close() throws MqttException {
    client_sub.close();
    client_sub.disconnect();
    }
    }

    =====================================分割线======================================================
    上面这些看着人畜无害,但是就在 messageArrived()里处理数据的时候就出问题了,上面的代码没有,是修改之后的,然后一并这个方法也挪走了

    不哔哔了,贴代码
    PushCallback 实现 MqttCallback 划重点


    @Slf4j
    public class PushCallback implements MqttCallback {

    @Autowired
    private McListener mcListener;


    public void connectionLost(Throwable cause) {
    mcListener.reConnect();
    }

    public void deliveryComplete(IMqttDeliveryToken token) {
    log.error("deliveryComplete---------" + token.isComplete());
    }

    public void messageArrived(String topic, MqttMessage message) throws Exception {
    log.debug("接收消息主题 : " + topic);
    String res = new String(message.getPayload());
    log.debug("接收消息内容 : " + res);
    SendMsg.sendMsg.sendMsgtoCust(res,topic);

    }




       =============================================重点这里=============================================
        所有相关数据库一类的操作也好其他逻辑也好在这里写

        sendMsgtoCust()就是你的方法名,里面写你的逻辑


    @Component
    public static class SendMsg{


    private static SendMsg sendMsg; //必须要重写一下!!


    @PostConstruct
    public void init(){
    sendMsg = this;
    }
          
    public void sendMsgtoCust(String msg,String topic){
    try {

    int type;
    if (topic.equals("sports/football/match.v1")){
    type = 1;
    } else {
    type = 2;
    }

    WsClient.send(msg,type);
    // 判断是否连接成功,未成功后面发送消息时会报错

    log.info("推送成功");
    } catch (Exception e) {

    e.printStackTrace();
    }
    }

    }

    }

    调用的时候     SendMsg.sendMsg.sendMsgtoCust(res,topic);  嗯,就可以了,理论太菜,有空研究

  • 相关阅读:
    Android学习第三天
    Android学习第二天(从零开始手动创建项目)
    【k8s】Pod-containers
    【k8s】Pod-Guaranteed
    【k8s】Pod-Burstable
    【k8s】Pod-BestEffort
    【k8s】Pod-qosClass
    【k8s】Pod-readinessGates
    【k8s】Pod-containerStatuses
    【k8s】Pod-conditions
  • 原文地址:https://www.cnblogs.com/michaelcnblogs/p/15616449.html
Copyright © 2020-2023  润新知