SpringBoot整合MQTT

SpringBoot整合MQTT

环境:

jdk:1.8

一、导入依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-configuration-processor</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.integration</groupId>
    <artifactId>spring-integration-mqtt</artifactId>
</dependency>

二、添加配置

com:
  mqtt:
    url: tcp://broker.emqx.io:1883
    clientId: mqttx_fd53fddgvkusg1389  # id必须在当前服务器上唯一
    topic: dreamstudio/#
    username:
    password:
    timeout: 10
    keepalive: 20

三、配置类

@Slf4j
@Configuration
@ConfigurationProperties(prefix = "com.mqtt")     //对应yml文件中的com下的mqtt文件配置
public class MqttConfiguration {
    private String url;
    private String clientId;
    private String topic;
    private String username;
    private String password;
    private String timeout;
    private String keepalive;
    public String getUrl() {
        return url;
    }
    public void setUrl(String url) {
        this.url = url;
    }
    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
    public String getClientId() {
        return clientId;
    }
    public void setClientId(String clientId) {
        this.clientId = clientId;
    }
    public String getTopic() {
        return topic;
    }
    public void setTopic(String topics) {
        this.topic = topics;
    }
    public String getTimeout() {
        return timeout;
    }
    public void setTimeout(String timeout) {
        this.timeout = timeout;
    }
    public String getKeepalive() {
        return keepalive;
    }
    public void setKeepalive(String keepalive) {
        this.keepalive = keepalive;
    }
    
    @Bean
    public MyMQTTClient myMQTTClient() {
        MyMQTTClient myMQTTClient = new MyMQTTClient(url, username, password, clientId, Integer.parseInt(timeout), Integer.parseInt(keepalive));
        for (int i = 0; i < 10; i++) {
            try {
                myMQTTClient.connect();
                //不同的主题
                myMQTTClient.subscribe(topic, 1);
                return myMQTTClient;
            } catch (MqttException e) {
                log.error("MQTT connect exception,connect time = " + i);
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e1) {
                    e1.printStackTrace();
                }
            }
        }
        return myMQTTClient;
    }
}

四、MQTT客户端

@Slf4j
public class MyMQTTClient {
    private static MqttClient client;
    private String url;
    private String username;
    private String password;
    private String clientId;
    private int timeout;
    private int keepalive;

    public MyMQTTClient(String url, String username, String password, String clientId, int timeOut, int keepAlive) {
        this.url = url;
        this.username = username;
        this.password = password;
        this.clientId = clientId;
        this.timeout = timeOut;
        this.keepalive = keepAlive;
    }

    public static MqttClient getClient() {
        return client;
    }

    public static void setClient(MqttClient client) {
        MyMQTTClient.client = client;
    }

    public MqttConnectOptions setMqttConnectOptions(String username, String password, int timeout, int keepalive) {
        MqttConnectOptions options = new MqttConnectOptions();
        options.setUserName(username);
        options.setPassword(password.toCharArray());
        options.setConnectionTimeout(timeout);
        options.setKeepAliveInterval(keepalive);
        options.setCleanSession(true);
        options.setAutomaticReconnect(true);
        return options;
    }

    public void connect() throws MqttException {
        if (client == null) {
            client = new MqttClient(url, clientId, new MemoryPersistence());
            client.setCallback(new MyMQTTCallback(MyMQTTClient.this));
        }
        MqttConnectOptions mqttConnectOptions = setMqttConnectOptions(username, password, timeout, keepalive);
        if (!client.isConnected()) {
            client.connect(mqttConnectOptions);
        } else {
            client.disconnect();
            client.connect(mqttConnectOptions);
        }
        log.info("MQTT connect success");
    }

    public void publish(String pushMessage, String topic) {
        publish(pushMessage, topic, 0, false);
    }

    public void publish(String pushMessage, String topic, int qos, boolean retained) {
        MqttMessage message = new MqttMessage();
        message.setPayload(pushMessage.getBytes());
        message.setQos(qos);
        message.setRetained(retained);
        MqttTopic mqttTopic = MyMQTTClient.getClient().getTopic(topic);
        if (null == mqttTopic) {
            log.error("topic is not exist");
        }
        MqttDeliveryToken token;
        synchronized (this) {
            try {
                assert mqttTopic != null;
                token = mqttTopic.publish(message);
                token.waitForCompletion(1000L);
            } catch (MqttException e) {
                e.printStackTrace();
            }
        }
    }
    
    public void subscribe(String topic, int qos) {
        try {
            MyMQTTClient.getClient().subscribe(topic, qos);
        } catch (MqttException e) {
            e.printStackTrace();
        }
    }
}

五、MQTT回调

@Slf4j
@Configuration
public class MyMQTTCallback implements MqttCallback {

    private MyMQTTClient myMQTTClient;


    public MyMQTTCallback(MyMQTTClient myMQTTClient) {
        this.myMQTTClient = myMQTTClient;
    }

    @Override
    public void connectionLost(Throwable throwable) {
        log.error("mqtt connectionLost 连接断开,5S之后尝试重连: {}", throwable.getMessage());
        long reconnectTimes = 1;
        while (true) {
            try {
                if (MyMQTTClient.getClient().isConnected()) {
                    log.warn("mqtt reconnect success end");
                    return;
                }
                log.warn("mqtt reconnect times = {} try again...", reconnectTimes++);
                MyMQTTClient.getClient().reconnect();
            } catch (MqttException e) {
                log.error(e.toString());
            }
            try {
                Thread.sleep(5000);
            } catch (InterruptedException ignored) {
            }
        }
    }

    @Override
    public void messageArrived(String topic, MqttMessage mqttMessage) {
        try {
            String msg = new String(mqttMessage.getPayload());
            log.info("接收消息主题 : {},接收消息内容 : {}", topic, msg);
            MqttMessageHandler.receive(topic, msg); //业务
        } catch (Exception e) {
            log.error(e.toString());
        }
    }

    @Override
    public void deliveryComplete(IMqttDeliveryToken iMqttDeliveryToken) {
        log.info("==========deliveryComplete={}==========", iMqttDeliveryToken.isComplete());
    }
//    @Component
//    public static class SaveData {
//        @Autowired
//        private WebSocket webSocket;
//
//        private static SaveData saveData;
//        @PostConstruct
//        public void init() {
//            saveData = this;
//            saveData.webSocket = webSocket;
//        }
//    }
}

主要是实现MqttCallback接口,该接口有三个需要实现的方法:

public interface MqttCallback {
    void connectionLost(Throwable cause);

    void messageArrived(String topic, MqttMessage message) throws Exception;

    void deliveryComplete(IMqttDeliveryToken token);
}

第一个方法会在断开连接时调用

第二个方法会在接收消息时调用

第三个方法会在发送消息成功时调用

注意:

  • 必须将messageArrived中的异常 try-catch掉 不然会莫名奇妙重连,并且连不上。
  • 该类中无法注入ioc容器中的Bean,若是要注入,则需要像注释掉的静态内部类一样操作。
  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值