最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

SpringBoot整合MQTT協(xié)議完整教程,如何實現(xiàn)低功耗物聯(lián)網(wǎng)通信?

 更新時間:2026年07月25日 09:34:45   作者:程序員一只長毛橘  
還在為物聯(lián)網(wǎng)通信協(xié)議選擇發(fā)愁?本文手把手教你用SpringBoot整合MQTT代理Mosquitto,從依賴引入到配置發(fā)布訂閱,詳細講解如何利用MQTT的低開銷、高容錯特性,實現(xiàn)可靠數(shù)據(jù)傳輸,并重點解決消息保留問題,通過設置Retained參數(shù),讓你的訂閱者只收即時消息

mosquitto的簡介

MQTT(MQ Telemetry Transport),消息隊列遙測傳輸協(xié)議,輕量級的發(fā)布/訂閱協(xié)議, 適用于一些條件比較苛刻的環(huán)境,進行低帶寬、不可靠或間歇性的通信。目前已經(jīng)是物聯(lián)網(wǎng)消息通信事實上的標準協(xié)議了。

值得一提的是mqtt提供三種不同質量的消息服務:

在工業(yè)上使用MQTT協(xié)議來進行物聯(lián)網(wǎng)數(shù)據(jù)傳輸,主要看中了以下優(yōu)點:

  1. 低協(xié)議開銷。它的每消息標題可以短至 2 個字節(jié)。 容錯性好。
  2. 物聯(lián)網(wǎng)的網(wǎng)絡環(huán)境往往比較惡劣,MQTT能從斷開故障中恢復,并且不需要額外的編碼(如果使用HTTP則需要實現(xiàn)重試代碼)。
  3. 低功耗。MQTT專門為了低功耗的目標而設計
  4. 最多能接受百萬級別的客戶端。

Mosquitto就是這樣一個MQTT協(xié)議的完整實現(xiàn)。

這里我工作中所用到了springBoot整合mosquitto,特此記錄一下,有需要的小伙伴,希望能幫到你,這里是用maven構建的。

1. 引入jar包依賴

<dependency>
    <groupId>org.springframework.integration</groupId>
    <artifactId>spring-integration-core</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-integration</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.integration</groupId>
    <artifactId>spring-integration-stream</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.integration</groupId>
    <artifactId>spring-integration-mqtt</artifactId>
</dependency>

2. application.yml 配置文件

spring:
  #mqtt配置
  mqtt:
    send:
      #完成超時時間
      completionTimeout: 3000
      #通過mqtt發(fā)送消息驗證所需用戶名
      username: test1
      #通過mqtt發(fā)送消息驗證所需密碼
      password: test1
      #連接的mqtt地址
      url: tcp: id:1883
      #客戶端id
      clientId: clint1
      #推送主題  后面跟著#是監(jiān)控下面所有的話題
      topic: topic
      #topic: my-test
      keepAliveInterval: 20
      connectionTimeout: 3000

3. mqtt的配置文件(初始客戶端,主題,發(fā)布,訂閱等消息)

創(chuàng)建MqttConfig類

import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.integration.annotation.ServiceActivator;
import org.springframework.integration.channel.DirectChannel;
import org.springframework.integration.core.MessageProducer;
import org.springframework.integration.mqtt.core.DefaultMqttPahoClientFactory;
import org.springframework.integration.mqtt.core.MqttPahoClientFactory;
import org.springframework.integration.mqtt.inbound.MqttPahoMessageDrivenChannelAdapter;
import org.springframework.integration.mqtt.outbound.MqttPahoMessageHandler;
import org.springframework.integration.mqtt.support.DefaultPahoMessageConverter;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.MessageHandler;
import org.springframework.util.StringUtils;

/**
 * @program: mg_parse
 * @description: TODO  MQTT配置,生產(chǎn)者
 * @author: 
 * @create: 
 **/
@Configuration
public class MqttConfig {
    private static final byte[] WILL_DATA;
    static {
        WILL_DATA = "offline".getBytes();
    }
    /**
     * mqtt訂閱者使用信道名稱
     */
    public static final String CHANNEL_NAME_IN = "mqttInboundChannel";
    /**
     * mqtt發(fā)布者信道名稱
     */
    public static final String CHANNEL_NAME_OUT = "mqttOutboundChannel";
    /**
     * mqtt發(fā)送者用戶名
     */
    @Value("${spring.mqtt.send.username}")
    private String username;
    /**
     * mqtt發(fā)送者密碼
     */
    @Value("${spring.mqtt.send.password}")
    private String password;
    /**
     * mqtt發(fā)送者url
     */
    @Value("${spring.mqtt.send.url}")
    private String hostUrl;
    /**
     * mqtt發(fā)送者客戶端id
     */
    @Value("${spring.mqtt.send.clientId}")
    private String clientId;
    /**
     * mqtt發(fā)送者主題
     */
    @Value("${spring.mqtt.send.topic}")
    private String msgTopic;
    /**
     * mqtt發(fā)送者超時時間
     */
    @Value("${spring.mqtt.send.completionTimeout}")
    private int completionTimeout ;
    /**
     * @author liujianfu
     * @description
     */
    @Value("${spring.mqtt.send.keepAliveInterval}")
    private int keepAliveInterval;
    /**
     * @author liujianfu
     * @description
     */
    @Value("${spring.mqtt.send.connectionTimeout}")
    private int connectionTimeout;

    @Autowired
    private MqttCallbackHandler mqttCallbackHandler;


    /**
     * @author liujianfu
     * @description   新建MqttConnectionOptionsBean  MQTT連接器選項
     * @date 2021/8/17 10:34
     * @param
     * @return org.eclipse.paho.client.mqttv3.MqttConnectOptions
     */
    @Bean
    public MqttConnectOptions getSenderMqttConnectOptions(){
        MqttConnectOptions options=new MqttConnectOptions();
        // 設置連接的用戶名
        if(!username.trim().equals("")){
            //將用戶名去掉前后空格
            options.setUserName(username);
        }
        // 設置連接的密碼
        options.setPassword(password.toCharArray());
        // 轉化連接的url地址
        String[] uris={hostUrl};
        // 設置連接的地址
        options.setServerURIs(uris);
        // 設置超時時間 單位為秒
        options.setConnectionTimeout(completionTimeout);
        // 設置會話心跳時間 單位為秒 服務器會每隔1.5*20秒的時間向客戶端發(fā)送心跳判斷客戶端是否在線
        // 但這個方法并沒有重連的機制
        options.setKeepAliveInterval(keepAliveInterval);
        // 設置“遺囑”消息的話題,若客戶端與服務器之間的連接意外中斷,服務器將發(fā)布客戶端的“遺囑”消息。
        //設置超時時間
        options.setConnectionTimeout(connectionTimeout);
        options.setCleanSession(true);
        options.setAutomaticReconnect(true);
        return options;
    }
    /**
     *創(chuàng)建MqttPathClientFactoryBean
     */
    @Bean
    public MqttPahoClientFactory senderMqttClientFactory() {
        //創(chuàng)建mqtt客戶端工廠
        DefaultMqttPahoClientFactory factory = new DefaultMqttPahoClientFactory();
        //設置mqtt的連接設置
        factory.setConnectionOptions(getSenderMqttConnectOptions());
        return factory;
    }
    /**
     * 發(fā)布者-MQTT信息通道(生產(chǎn)者)
     */
    @Bean(name = CHANNEL_NAME_OUT)
    public MessageChannel mqttOutboundChannel() {
        return new DirectChannel();
    }


    /**
     * 發(fā)布者-MQTT消息處理器(生產(chǎn)者)  將channel綁定到MqttClientFactory上
     *
     * @return {@link org.springframework.messaging.MessageHandler}
     */
    @Bean
    @ServiceActivator(inputChannel = CHANNEL_NAME_OUT)
    public MessageHandler mqttOutbound() {
        //創(chuàng)建消息處理器
        MqttPahoMessageHandler messageHandler = new MqttPahoMessageHandler(
                clientId+"_pub",
                senderMqttClientFactory());
        //設置消息處理類型為異步
        messageHandler.setAsync(true);
        //設置消息的默認主題
        messageHandler.setDefaultTopic(msgTopic);
        messageHandler.setDefaultRetained(false);
        //1.重新連接MQTT服務時,不需要接收該主題最新消息,設置retained為false;
        //2.重新連接MQTT服務時,需要接收該主題最新消息,設置retained為true;
        return messageHandler;
    }



    /************                             消費者,訂閱者的消費信息                               *****/

    /**
     * MQTT信息通道(消費者)
     *
     */
    @Bean(name = CHANNEL_NAME_IN)
    public MessageChannel mqttInboundChannel() {
        return new DirectChannel();
    }
    /**
     * MQTT消息訂閱綁定(消費者)
     *
     */
    @Bean
    public MessageProducer inbound() {
        System.out.println("topics:"+msgTopic);
        // 可以同時消費(訂閱)多個Topic
        MqttPahoMessageDrivenChannelAdapter adapter =
                new MqttPahoMessageDrivenChannelAdapter(
                        clientId+"_sub", senderMqttClientFactory(), msgTopic);
        adapter.setCompletionTimeout(5000);
        adapter.setConverter(new DefaultPahoMessageConverter());
        adapter.setQos(0);
        // 設置訂閱通道
        adapter.setOutputChannel(mqttInboundChannel());
        return adapter;
    }

    /**
     * MQTT消息處理器(消費者)
     *
     */
    @Bean
    @ServiceActivator(inputChannel = CHANNEL_NAME_IN)
    public MessageHandler handler() {
        return message -> {
            String topic = message.getHeaders().get("mqtt_receivedTopic").toString();
            String payload = message.getPayload().toString();
            mqttCallbackHandler.handle(topic,payload);
        };
    }
}

4. 發(fā)送接口網(wǎng)關MqSendMessageGateWay

import org.springframework.integration.annotation.MessagingGateway;
import org.springframework.integration.mqtt.support.MqttHeaders;
import org.springframework.messaging.handler.annotation.Header;
import org.springframework.stereotype.Component;

/**
 * @program: mg_parse
 * @description:
 * @author: 
 * @create:
 **/

@Component
@MessagingGateway(defaultRequestChannel = MqttConfig.CHANNEL_NAME_OUT)
public interface MqSendMessageGateWay {
    /**
     * 默認的消息機制
     * @param data
     */
    void sendToMqtt(String data);

    /**
     * 發(fā)送消息 向mqtt指定topic發(fā)送消息
     * @param topic
     * @param payload
     */
    void sendToMqtt(@Header(MqttHeaders.TOPIC) String topic, String payload);

    /**
     * 發(fā)送消息 向mqtt指定topic發(fā)送消息
     * @param topic
     * @param qos
     * @param payload
     */
    void sendToMqtt(@Header(MqttHeaders.TOPIC) String topic, @Header(MqttHeaders.QOS) int qos, String payload);
}

5. 消息訂閱類MqttCallbackHandler

import org.springframework.stereotype.Service;

/**
 * @program: mg_parse
 * @description:
 * @author: 
 * @create: 
 **/
@Service
public class MqttCallbackHandler {

    public void handle(String topic, String payload){
        // 根據(jù)topic分別進行消息處理。
        System.out.println("MqttCallbackHandle:" + topic + "|"+ payload);
    }
}

6. 發(fā)布生產(chǎn),這里用controller層來測試

在生產(chǎn)中,啟動監(jiān)聽以后,使用service層來發(fā)送主題

@Autowired
private MqSendMessageGateWay mqSendMessageGateWay;

@RequestMapping("/send")
@ResponseBody
private ResponseEntity<String> send(){
    String data = "我是springboot發(fā)送的數(shù)據(jù)";
    mqSendMessageGateWay.sendToMqtt(data);
    // return R.ok("OK");
    return new ResponseEntity<>("OK", HttpStatus.OK);
}
/**
 * 動態(tài)增加主題
 * @param
 * @param
 */
@ResponseBody
@RequestMapping("/sendToTopic")
private ResponseEntity<String> sendToTopic(){
    String topic = "sharjeck/ai/test/out";
    String data = "這是出的主題";
    mqSendMessageGateWay.sendToMqtt(topic,data);
    return new ResponseEntity<>("OK", HttpStatus.OK);
}

7. 啟動springboot啟動類即可

8. SpringBoot連接MQTT進行發(fā)布消息時取消保留歷史消息

在發(fā)布完消息后,另一個新的訂閱者在開始訂閱這個消息后會收到之前發(fā)布的歷史消息,現(xiàn)在不需要使其收到歷史消息,只需要收到即時消息

在進行發(fā)布消息時調(diào)用發(fā)布消息時

有一個參數(shù)叫retained。

Retained 消息是指在 PUBLISH 數(shù)據(jù)包中 Retain 標識設為 1 的消息,Broker 收到這樣的 publish 包以后,將保存這個消息,當有一個新的訂閱者訂閱相應主 題的時候,Broker 會馬上將這個消息發(fā)送給訂閱者。

這里生產(chǎn)者,生產(chǎn)的時候把retained設置為flase的時候,便不會保留歷史信息!

Qos的等級,可根據(jù)業(yè)務進行設定,到此,配置完成。

總結

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關文章

  • java通過AOP實現(xiàn)全局日志打印詳解

    java通過AOP實現(xiàn)全局日志打印詳解

    最近自己一直再看現(xiàn)有微服務的日志模塊,發(fā)現(xiàn)就是使用AOP來做controller層的日志處理,加上項目在進行架構優(yōu)化,這篇文章主要給大家介紹了關于java通過AOP實現(xiàn)全局日志打印的相關資料,需要的朋友可以參考下
    2022-01-01
  • Java字節(jié)碼指令集的使用詳細

    Java字節(jié)碼指令集的使用詳細

    本篇文章對Java字節(jié)碼指令集的使用進行了詳細的介紹。需要的朋友參考下
    2013-05-05
  • SpringBoot集成WebSocket長連接實際應用詳解

    SpringBoot集成WebSocket長連接實際應用詳解

    這篇文章主要介紹了SpringBoot集成WebSocket長連接實際應用詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-06-06
  • SpringBoot測試junit遇到的坑及解決

    SpringBoot測試junit遇到的坑及解決

    這篇文章主要介紹了SpringBoot測試junit遇到的坑及解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-01-01
  • springboot使用nacos的示例詳解

    springboot使用nacos的示例詳解

    這篇文章主要介紹了springboot使用nacos的示例代碼,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-12-12
  • Spring中的編程式事務和聲明式事務

    Spring中的編程式事務和聲明式事務

    Spring框架中,事務管理可以通過編程式事務和聲明式事務兩種方式實現(xiàn),編程式事務通過手動編碼控制事務的開始、提交和回滾,允許開發(fā)者精確控制事務,但增加了代碼復雜度,聲明式事務則通過@EnableTransactionManagement注解啟用事務管理
    2024-11-11
  • springboot注解Aspect實現(xiàn)方案

    springboot注解Aspect實現(xiàn)方案

    本文提供一種自定義注解,來實現(xiàn)業(yè)務審批操作的DEMO,不包含審批流程的配置功能。對springboot注解Aspect實現(xiàn)方案感興趣的朋友一起看看吧
    2022-01-01
  • Java8時間api之LocalDate/LocalDateTime的用法詳解

    Java8時間api之LocalDate/LocalDateTime的用法詳解

    在項目中,時間的使用必不可少,而java8之前的時間api?Date和Calander等在使用上存在著很多問題,于是,jdk1.8引進了新的時間api-LocalDateTime,本文就來講講它的具體使用吧
    2023-05-05
  • 解決FeignClient發(fā)送post請求異常的問題

    解決FeignClient發(fā)送post請求異常的問題

    這篇文章主要介紹了FeignClient發(fā)送post請求異常的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-07-07
  • Java8中關于Function.identity()的使用

    Java8中關于Function.identity()的使用

    這篇文章主要介紹了Java8中關于Function.identity()的使用,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-05-05

最新評論

陆河县| 西丰县| 谢通门县| 新竹县| 永川市| 新巴尔虎左旗| 嘉善县| 湛江市| 赤城县| 林甸县| 新巴尔虎左旗| 汨罗市| 广丰县| 郑州市| 永泰县| 绵阳市| 保康县| 阿拉善左旗| 柳林县| 独山县| 沁阳市| 收藏| 山东省| 隆化县| 龙岩市| 手游| 乐亭县| 宁海县| 应城市| 和平区| 栖霞市| 依安县| 蓝田县| 鄂伦春自治旗| 闽清县| 缙云县| 城步| 榆树市| 安达市| 东阳市| 休宁县|