MQTT实战之在vue和java中使用

在VUE中使用MQTT

1、创建vue项目(使用node版本为20.12.0)

>>npm create vite@latest
Need to install the following packages:
create-vite@6.1.1
Ok to proceed? (y) y
√ Project name: ... mqtt-vue
√ Select a framework: » Vue
√ Select a variant: » JavaScript

2、进入项目目录,安装依赖

npm install
npm install element-plus --save
npm install mqtt --save

3、在main.js

import { createApp } from 'vue'
import './style.css'
import App from './App.vue'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'

const app = createApp(App)
app.use(ElementPlus)
app.mount('#app')

4、在components文件目录下创建MqttDemo.vue

<script setup>
//消息质量取值数组
const qosList = [0,1,2]
</script>

<template>
    <div class="mqtt-demo">
        <el-card>
            <h3>配置信息</h3>
            <el-form label-position="top">
                <el-row :gutter="20">
                    <el-col :span="8">
                        <el-form-item prop="protocol" label="选择协议">
                            <el-select>
                                <el-option label="ws://" value="ws"></el-option>
                                <el-option label="wss://" value="wss"></el-option>
                            </el-select>
                        </el-form-item>
                    </el-col>

                    <el-col :span="8">
                        <el-form-item prop="host" label="主机地址">
                            <el-input></el-input>
                        </el-form-item>
                    </el-col>

                    <el-col :span="8">
                        <el-form-item prop="port" label="端口号">
                            <el-input type="number" placeholder="8083/8084"></el-input>
                        </el-form-item>
                    </el-col>

                    <el-col :span="8">
                        <el-form-item prop="clientId" label="客户端ID">
                            <el-input></el-input>
                        </el-form-item>
                    </el-col>

                    <el-col :span="8">
                        <el-form-item prop="username" label="用户名">
                            <el-input></el-input>
                        </el-form-item>
                    </el-col>

                    <el-col :span="8">
                        <el-form-item prop="password" label="密码">
                            <el-input></el-input>
                        </el-form-item>
                    </el-col>

                    <el-col :span="24">
                        <el-button type="primary">建立连接</el-button>
                        <el-button type="danger">断开连接</el-button>
                    </el-col>
                </el-row>
            </el-form>
        </el-card>

        <el-card>
            <h3>订阅主题</h3>
            <el-form label-position="top">
                <el-row :gutter="20">
                    <el-col :span="8">
                        <el-form-item prop="topic" label="Topic">
                            <el-input></el-input>
                        </el-form-item>
                    </el-col>
                    <el-col :span="8">
                        <el-form-item prop="qos" label="Qos">
                            <el-select>
                                <el-option
                                    v-for="qos in qosList"
                                    :key="qos"
                                    :label="qos"
                                    :value="qos"></el-option>
                            </el-select>
                        </el-form-item>
                    </el-col>
                    <el-col :span="8">
                        <el-button type="primary" class="sub-btn">订阅主题</el-button>
                        <el-button type="primary" class="sub-btn">取消订阅</el-button>
                    </el-col>
                </el-row>
            </el-form>
        </el-card>

        <el-card>
            <h3>发布消息</h3>
            <el-form label-position="top">
                <el-row :gutter="20">
                    <el-col :span="8">
                        <el-form-item prop="topic" label="Topic">
                            <el-input></el-input>
                        </el-form-item>
                    </el-col>
                    <el-col :span="8">
                        <el-form-item prop="payload" label="Payload">
                            <el-input></el-input>
                        </el-form-item>
                    </el-col>
                    <el-col :span="8">
                        <el-form-item prop="qos" label="Qos">
                            <el-select>
                                <el-option
                                    v-for="qos in qosList"
                                    :key="qos"
                                    :label="qos"
                                    :value="qos"></el-option>
                            </el-select>
                        </el-form-item>
                    </el-col>
                </el-row>
            </el-form>
            <el-col :span="24" class="text-right">
                <el-button type="primary">发布消息</el-button>
            </el-col>
        </el-card>

        <el-card>
            <h3>接收到的消息</h3>
            <el-col :span="24">
                <el-input
                    type="textarea"
                    :rows="3"
                    readonly></el-input>
            </el-col>
        </el-card>
    </div>
</template>

5、在App.vue中

<script setup>
import MqttDemo from './components/MqttDemo.vue'
</script>

<template>
  <MqttDemo />
</template>
<style scoped>

</style>

6、建立-断开连接

<script setup>
import {ref} from 'vue';
import mqtt from 'mqtt';
//消息质量取值数组
const qosList = [0,1,2];

//定义连接参数的对象
const connectionInfo = ref({
    protocol:'ws',
    host:'127.0.0.1',
    port:'8083',
    clientId:'emqx_vue_client_'+Math.random().toString().substring(2,8),
    username:'user',
    password:'123456'
})

//建立连接
const clientInitData = ref({
    connected: false
})
const client = ref({})
const createConnection = () => {
    const { protocol, host, port, clientId, ...options } = connectionInfo.value
    const connectionUrl = `${protocol}://${host}:${port}/mqtt`
    client.value = mqtt.connect(connectionUrl,options)
    clientInitData.value.connected = true
}

//断开连接
const closeConnection = () =>{
    client.value.end(false,()=>{
        clientInitData.value.connected = false;
    })
}

</script>

============================================================================================================

<el-card>
            <h3>配置信息</h3>
            <el-form label-position="top">
                <el-row :gutter="20">
                    <el-col :span="8">
                        <el-form-item prop="protocol" label="选择协议">
                            <el-select v-model="connectionInfo.protocol">
                                <el-option label="ws://" value="ws"></el-option>
                                <el-option label="wss://" value="wss"></el-option>
                            </el-select>
                        </el-form-item>
                    </el-col>

                    <el-col :span="8">
                        <el-form-item prop="host" label="主机地址">
                            <el-input v-model="connectionInfo.host"></el-input>
                        </el-form-item>
                    </el-col>

                    <el-col :span="8">
                        <el-form-item prop="port" label="端口号">
                            <el-input type="number" v-model="connectionInfo.port" placeholder="8083/8084"></el-input>
                        </el-form-item>
                    </el-col>

                    <el-col :span="8">
                        <el-form-item prop="clientId" label="客户端ID">
                            <el-input v-model="connectionInfo.clientId"></el-input>
                        </el-form-item>
                    </el-col>

                    <el-col :span="8">
                        <el-form-item prop="username" label="用户名">
                            <el-input v-model="connectionInfo.username"></el-input>
                        </el-form-item>
                    </el-col>

                    <el-col :span="8">
                        <el-form-item prop="password" label="密码">
                            <el-input v-model="connectionInfo.password"></el-input>
                        </el-form-item>
                    </el-col>

                    <el-col :span="24">
                        <el-button type="primary" :disabled="clientInitData.connected" @click="createConnection">建立连接</el-button>
                        <el-button type="danger" :disabled="!clientInitData.connected" @click="closeConnection">断开连接</el-button>
                    </el-col>
                </el-row>
            </el-form>
        </el-card>

7、订阅主题-取消订阅

import { ElMessage } from 'element-plus'

//订阅主题对象
const subscriptionInfo = ref({
    topic:'',
    qos: 0
})

//接收消息对象
const receiverMessages = ref({})
const subscriptionInitData = ref({
    subscription: false
})

//订阅主题
const subscriptionTopicHandler = () =>{
    const { topic, qos } = subscriptionInfo.value
    client.value.subscribe(topic, { qos }, (error, res) => {
        if(error){
            ElMessage.error("订阅主题失败")
            return ;
        }

        subscriptionInitData.value.subscription=true

        //给连接对象注册接收消息的事件
        client.value.on('message',(topic, message)=>{
            receiverMessages.value = topic + "------>" + message
        })
        ElMessage({
            message: '订阅主题成功',
            type: 'success',
        })
    })
}

//取消订阅
const unSubscriptionTopicHandler = () => {
    const { topic, qos } = subscriptionInfo.value
    client.value.unsubscribe(topic, { qos }, (error, res)=>{
        if(error){
            ElMessage.error("取消主题订阅失败")
            return ;
        }
        subscriptionInitData.value.subscription = false;
        ElMessage({
            message: '取消订阅成功',
            type: 'success',
        })
    })
}

============================================================================================================

<el-card>
            <h3>订阅主题</h3>
            <el-form label-position="top">
                <el-row :gutter="20">
                    <el-col :span="8">
                        <el-form-item prop="topic" label="Topic">
                            <el-input v-model="subscriptionInfo.topic"></el-input>
                        </el-form-item>
                    </el-col>
                    <el-col :span="8">
                        <el-form-item prop="qos" label="Qos">
                            <el-select v-model="subscriptionInfo.qos">
                                <el-option
                                    v-for="qos in qosList"
                                    :key="qos"
                                    :label="qos"
                                    :value="qos"></el-option>
                            </el-select>
                        </el-form-item>
                    </el-col>
                    <el-col :span="8">
                        <el-button type="primary" class="sub-btn" :disabled="subscriptionInitData.subscription" @click="subscriptionTopicHandler">订阅主题</el-button>
                        <el-button type="primary" class="sub-btn" :disabled="!subscriptionInitData.subscription" @click="unSubscriptionTopicHandler">取消订阅</el-button>
                    </el-col>
                </el-row>
            </el-form>
        </el-card>

8、发布消息

//发送消息对象
const publishInfo= ref({
    topic: '',
    qos: 0,
    payload: ''
})

//发布消息
const doPublish = () =>{
    const { topic, qos, payload } = publishInfo.value
    client.value.publish(topic, payload, { qos }, (error, res) => {
        if(error){
            ElMessage.error("发布消息失败")
            return;
        }
        ElMessage({
            message: '发布消息成功',
            type: 'success',
        })
    })
}

============================================================================================================

<el-card>
    <h3>发布消息</h3>
    <el-form label-position="top">
        <el-row :gutter="20">
            <el-col :span="8">
                <el-form-item prop="topic" label="Topic">
                    <el-input v-model="publishInfo.topic"></el-input>
                </el-form-item>
            </el-col>
            <el-col :span="8">
                <el-form-item prop="payload" label="Payload">
                    <el-input v-model="publishInfo.payload"></el-input>
                </el-form-item>
            </el-col>
            <el-col :span="8">
                <el-form-item prop="qos" label="Qos">
                    <el-select v-model="publishInfo.qos">
                        <el-option
                            v-for="qos in qosList"
                            :key="qos"
                            :label="qos"
                            :value="qos"></el-option>
                    </el-select>
                </el-form-item>
            </el-col>
        </el-row>
    </el-form>
    <el-col :span="24" class="text-right">
        <el-button type="primary" @click="doPublish">发布消息</el-button>
    </el-col>
</el-card>

<el-card>
    <h3>接收到的消息</h3>
    <el-col :span="24">
        <el-input v-model="receiverMessages"
            type="textarea"
            :rows="3"
            readonly></el-input>
    </el-col>
</el-card>

在java中使用MQTT

方式一:eclipse.paho.client.mqttv3

1、创建springboot项目,添加依赖

<!--        mqtt客户端依赖项-->
        <dependency>
            <groupId>org.eclipse.paho</groupId>
            <artifactId>org.eclipse.paho.client.mqttv3</artifactId>
            <version>1.2.0</version>
        </dependency>

2、建立连接

public void createConnection() throws MqttException {
        //定义连接相关参数
        String serverURI = "tcp://127.0.0.1:1883";
        String clientId = "pacho_client_123";

       //创建MqttClient对象
        MqttClient mqttClient = new MqttClient(serverURI, clientId, new MemoryPersistence());

        //创建MqttConnectOptions对象
        MqttConnectOptions mqttConnectOptions = new MqttConnectOptions();
        mqttConnectOptions.setUserName("user");
        mqttConnectOptions.setPassword("123456".toCharArray());
        mqttConnectOptions.setCleanSession(true);

        //发送建立连接的请求
        mqttClient.connect(mqttConnectOptions);

        //让当前方法处于阻塞状态
        while (true);
    }

3、发送消息

public void sendMsg() throws MqttException {
        //定义连接相关参数
        String serverURI = "tcp://127.0.0.1:1883";
        String clientId = "pacho_client_123";

        //创建MqttClient对象
        MqttClient mqttClient = new MqttClient(serverURI, clientId, new MemoryPersistence());

        //创建MqttConnectOptions对象
        MqttConnectOptions mqttConnectOptions = new MqttConnectOptions();
        mqttConnectOptions.setUserName("user");
        mqttConnectOptions.setPassword("123456".toCharArray());
        mqttConnectOptions.setCleanSession(true);

        //发送建立连接的请求
        mqttClient.connect(mqttConnectOptions);

        //发送消息对象
        MqttMessage mqttMessage = new MqttMessage();
        mqttMessage.setPayload("hello mqtt java client".getBytes(StandardCharsets.UTF_8));

        mqttClient.publish("aa",mqttMessage);   //主题,发送的消息

        //关闭连接
        mqttClient.disconnect();
        mqttClient.close();
    }

4、订阅主题、接收消息

public void receiveMsg() throws MqttException {
        //定义连接相关参数
        String serverURI = "tcp://127.0.0.1:1883";
        String clientId = "pacho_client_123";

        //创建MqttClient对象
        MqttClient mqttClient = new MqttClient(serverURI, clientId, new MemoryPersistence());

        //创建MqttConnectOptions对象
        MqttConnectOptions mqttConnectOptions = new MqttConnectOptions();
        mqttConnectOptions.setUserName("user");
        mqttConnectOptions.setPassword("123456".toCharArray());
        mqttConnectOptions.setCleanSession(true);

        mqttClient.setCallback(new MqttCallback() {
            @Override
            public void connectionLost(Throwable throwable) {    //连接丢失时执行
                System.out.println("connect lose...");
            }

            @Override
            public void messageArrived(String topic, MqttMessage mqttMessage) throws Exception {     //消息接收时执行
                System.out.println("topic--->"+topic);
                byte[] payload = mqttMessage.getPayload();
                System.out.println("msg--->"+new String(payload));
            }

            @Override
            public void deliveryComplete(IMqttDeliveryToken iMqttDeliveryToken) {      //消息接收完毕后执行
                System.out.println("delivery complete...");
            }
        });

        //发送建立连接的请求
        mqttClient.connect(mqttConnectOptions);

        //订阅主题
        mqttClient.subscribe("aa",2);

当给主题为aa发送消息时,运行结果显示

topic--->aa

msg--->{

        "msg": "aaacccc"

}

方式二:spring-integration-mqtt

1、创建springboot项目,添加依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.5.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>mqtt-java</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>mqtt-java</name>
    <description>mqtt-java</description>

    <properties>
        <java.version>1.8</java.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!--        springboot集成中间件的基础依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-integration</artifactId>
        </dependency>

<!--        springboot集成mqtt客户端的依赖-->
        <dependency>
            <groupId>org.springframework.integration</groupId>
            <artifactId>spring-integration-mqtt</artifactId>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.76</version>
        </dependency>
    </dependencies>

</project>

2、在application.yml中添加mqtt的配置信息

spring:
  mqtt:
    username: user
    password: 123456
    url: tcp://127.0.0.1:1883
    subClientId: sub_client_id_123
    subTopic: java/aa
    pubClientId: pub_client_id_123

3、添加读取mqtt配置信息的配置类MqttConfigurationProperties

package com.example.mqttjava;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;

@Data
@ConfigurationProperties(prefix="spring.mqtt")
public class MqttConfigurationProperties {
    private String username;
    private String password;
    private String url;
    private String subClientId;
    private String subTopic;
    private String pubClientId;
}

4、在启动类MqttJavaApplication中添加读取配置信息的注解

package com.example.mqttjava;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;

@SpringBootApplication
@EnableConfigurationProperties(value = MqttConfigurationProperties.class)
public class MqttJavaApplication {

    public static void main(String[] args) {
        SpringApplication.run(MqttJavaApplication.class, args);
    }

}

5、配置MQTT客户端连接工厂类MqttConfiguration

package com.example.mqttjava;

import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.integration.mqtt.core.DefaultMqttPahoClientFactory;
import org.springframework.integration.mqtt.core.MqttPahoClientFactory;

@Configuration
public class MqttConfiguration {
    @Autowired
    private MqttConfigurationProperties mqttConfigurationProperties;

    @Bean
    public MqttPahoClientFactory mqttPahoClientFactory(){
        DefaultMqttPahoClientFactory mqttPahoClientFactory = new DefaultMqttPahoClientFactory();
        MqttConnectOptions options = new MqttConnectOptions();
        options.setCleanSession(true);
        options.setUserName(mqttConfigurationProperties.getUsername());
        options.setPassword(mqttConfigurationProperties.getPassword().toCharArray());
        options.setServerURIs(new String[]{mqttConfigurationProperties.getUrl()});
        mqttPahoClientFactory.setConnectionOptions(options);
        return mqttPahoClientFactory;
    }
}

6、MQTT消息入站处理类MqttInboundConfiguration

首先创建一个消息通道,设置一个MQTT入栈适配器来订阅特定的主题并接收消息,然后将这些消息发送到消息通道,最后由指定的消息处理器来处理这些消息

package com.example.mqttjava;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.integration.annotation.ServiceActivator;
import org.springframework.integration.channel.DirectChannel;
import org.springframework.integration.core.MessageProducer;
import org.springframework.integration.mqtt.core.MqttPahoClientFactory;
import org.springframework.integration.mqtt.inbound.MqttPahoMessageDrivenChannelAdapter;
import org.springframework.integration.mqtt.support.DefaultPahoMessageConverter;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.MessageHandler;


@Configuration
public class MqttInboundConfiguration {
    @Autowired
    private MqttConfigurationProperties mqttConfigurationProperties;

    @Autowired
    private MqttPahoClientFactory mqttPahoClientFactory;

    @Autowired
    private ReceiverMessageHandler receiverMessageHandler;

    //消息通道
    @Bean
    public MessageChannel messageInboundChannel(){
        return new DirectChannel();
    }

    //配置入站适配器:设置要订阅的主题,指定消息相关属性
    @Bean
    public MessageProducer messageProducer(){
        MqttPahoMessageDrivenChannelAdapter mqttPahoMessageDrivenChannelAdapter = new MqttPahoMessageDrivenChannelAdapter(
                mqttConfigurationProperties.getUrl(),
                mqttConfigurationProperties.getSubClientId(),
                mqttPahoClientFactory,
                mqttConfigurationProperties.getSubTopic().split(",")
        );

        mqttPahoMessageDrivenChannelAdapter.setQos(1);
        mqttPahoMessageDrivenChannelAdapter.setConverter(new DefaultPahoMessageConverter());
        mqttPahoMessageDrivenChannelAdapter.setOutputChannel(messageInboundChannel());
        return mqttPahoMessageDrivenChannelAdapter;
    }

    @Bean
    @ServiceActivator(inputChannel = "messageInboundChannel")
    public MessageHandler messageHandler(){
        return  receiverMessageHandler;
    }
}

7、接收MQTT消息处理器ReceiverMessageHandler

package com.example.mqttjava;

import org.springframework.messaging.Message;
import org.springframework.messaging.MessageHandler;
import org.springframework.messaging.MessageHeaders;
import org.springframework.messaging.MessagingException;
import org.springframework.stereotype.Component;


@Component
public class ReceiverMessageHandler implements MessageHandler {

    @Override
    public void handleMessage(Message<?> message) throws MessagingException {
        Object payload = message.getPayload();
        System.out.println("payload:  "+payload);
        System.out.println("message:  "+message);
        MessageHeaders headers = message.getHeaders();
        String topicName = headers.get("mqtt_receivedTopic").toString();
        System.out.println("topicName: "+topicName);
    }
}

输出:

payload:  {
  "msg": "aaacccc"
}
message:  GenericMessage [payload={
  "msg": "aaacccc"
}, headers={mqtt_receivedRetained=true, mqtt_id=0, mqtt_duplicate=false, id=873967f5-6a6f-c092-f276-62ed1b1d3c18, mqtt_receivedTopic=java/aa, mqtt_receivedQos=0, timestamp=1738572747948}]
topicName: java/aa

8、MQTT消息出站处理类MqttOutboundConfiguration

  • @ServiceActivator(inputChannel = "mqttOutboundChannel"):这个注解将mqttOutBoundMessageHandler标记为一个服务激活器,并将其与mqttOutboundChannel消息通道关联起来。这意味着,当消息被发送到mqttOutboundChannel时,mqttOutBoundMessageHandler将负责处理这些消息(即将它们发送到MQTT代理)。

package com.example.mqttjava;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.integration.annotation.ServiceActivator;
import org.springframework.integration.channel.DirectChannel;
import org.springframework.integration.core.MessageProducer;
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;


@Configuration
public class MqttOutboundConfiguration {
    @Autowired
    private MqttConfigurationProperties mqttConfigurationProperties;

    @Autowired
    private MqttPahoClientFactory mqttPahoClientFactory;

    //配置消息通道
    @Bean
    public MessageChannel mqttOutboundChannel(){
        return new DirectChannel();
    }

    //配置出站消息处理器
    @Bean
    @ServiceActivator(inputChannel = "mqttOutboundChannel")
    public MessageHandler mqttOutBoundMessageHandler(){
        MqttPahoMessageHandler mqttPahoMessageHandler = new MqttPahoMessageHandler(
                mqttConfigurationProperties.getUrl(),
                mqttConfigurationProperties.getPubClientId(),
                mqttPahoClientFactory
        );
        mqttPahoMessageHandler.setDefaultQos(0);
        mqttPahoMessageHandler.setDefaultTopic("default");
        mqttPahoMessageHandler.setAsync(true);
        return mqttPahoMessageHandler;
    }

}

9、MQTT网关接口MqttGateway,用于向MQTT发送消息

package com.example.mqttjava;

import org.springframework.context.annotation.Bean;
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;

@Component
@MessagingGateway(defaultRequestChannel = "mqttOutboundChannel")
public interface MqttGateway {
    public abstract void sendMsgToMqtt(@Header(value = MqttHeaders.TOPIC) String topic, String payload);

    public abstract void sendMsgToMqtt(@Header(value = MqttHeaders.TOPIC) String topic, @Header(value = MqttHeaders.QOS) int qos, String payload);
}

10、向MQTT发送消息的服务类MqttMessageSender

package com.example.mqttjava;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class MqttMessageSender {
    @Autowired
    private MqttGateway mqttGateway;

    public void sendMsg(String topic, String msg){
        mqttGateway.sendMsgToMqtt(topic,msg);
    }

    public void sendMsg(String topic, int qos, String msg){
        mqttGateway.sendMsgToMqtt(topic, qos, msg);
    }
}

11、发送消息测试

package com.example.mqttjava;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest(classes = MqttJavaApplication.class)
public class MqttTest {
    @Autowired
    private MqttMessageSender mqttMessageSender;

    @Test
    public void sendToMsg(){
        mqttMessageSender.sendMsg("java/aa","hello");
    }
}

payload:  hello
message:  GenericMessage [payload=hello, headers={mqtt_receivedRetained=false, mqtt_id=0, mqtt_duplicate=false, id=35e8e42b-cc22-f4df-8ba1-b184616ded03, mqtt_receivedTopic=java/aa, mqtt_receivedQos=0, timestamp=1738572748073}]
topicName: java/aa

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/964042.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

oracle: 表分区>>范围分区,列表分区,散列分区/哈希分区,间隔分区,参考分区,组合分区,子分区/复合分区/组合分区

分区表 是将一个逻辑上的大表按照特定的规则划分为多个物理上的子表&#xff0c;这些子表称为分区。 分区可以基于不同的维度&#xff0c;如时间、数值范围、字符串值等&#xff0c;将数据分散存储在不同的分区 中&#xff0c;以提高数据管理的效率和查询性能&#xff0c;同时…

数据分析系列--⑥RapidMiner构建决策树(泰坦尼克号案例含数据)

一、资源下载 二、数据处理 1.导入数据 2.数据预处理 三、构建模型 1.构建决策树 2.划分训练集和测试集 3.应用模型 4.结果分析 一、资源下载 点击下载数据集 二、数据处理 1.导入数据 2.数据预处理 三、构建模型 1.构建决策树 虽然决策树已经构建,但对于大多数初学者或…

Unity游戏(Assault空对地打击)开发(4) 碰撞体和刚体的添加

前言 飞机和世界的大小关系不太对&#xff0c;我稍微缩小了一下飞机。 详细步骤 选中所有地形对象&#xff0c;如果没有圈起的部分&#xff0c;点击Add Component搜索添加。 接着选中Player对象&#xff0c;添加这两个组件&#xff0c;最好&#xff08;仅对于本项目开发&#x…

【Windows7和Windows10下从零搭建Qt+Leaflet开发环境】

Windows7和Windows10下从零搭建QtLeaflet开发环境 本文开始编写于2025年1月27日星期一&#xff08;农历&#xff1a;腊月二十八&#xff0c;苦逼的人&#xff0c;过年了还在忙工作&#xff09;。 第一章 概述 整个开发环境搭建需要的资源&#xff1a; 操作系统 Windows7_x6…

【游戏设计原理】97 - 空间感知

一、游戏空间的类型 将游戏设计中的空间设计单独提取出来&#xff0c;可以根据其结构、功能和玩家的交互方式划分为以下几种主要类型。这些类型可以单独存在&#xff0c;也可以组合使用&#xff0c;以创造更加复杂和有趣的游戏体验。 1. 线性空间 定义&#xff1a;空间设计是…

基于云计算、大数据与YOLO设计的火灾/火焰目标检测

摘要&#xff1a;本研究针对火灾早期预警检测需求&#xff0c;采用在Kaggle平台获取数据、采用云计算部署的方式&#xff0c;以YOLO11构建模型&#xff0c;使用云计算服务器训练模型。经训练&#xff0c;box loss从约3.5降至1.0&#xff0c;cls loss从约4.0降至1.0&#xff0c;…

【大数据技术】教程03:本机PyCharm远程连接虚拟机Python

本机PyCharm远程连接虚拟机Python 注意:本文需要使用PyCharm专业版。 pycharm-professional-2024.1.4VMware Workstation Pro 16CentOS-Stream-10-latest-x86_64-dvd1.iso写在前面 本文主要介绍如何使用本地PyCharm远程连接虚拟机,运行Python脚本,提高编程效率。 注意: …

bypass hcaptcha、hcaptcha逆向

可以过steam&#xff0c;已支持并发&#xff0c;欢迎询问&#xff01; 有事危&#xff0c;ProfessorLuoMing

Mac本地部署DeekSeek-R1下载太慢怎么办?

Ubuntu 24 本地安装DeekSeek-R1 在命令行先安装ollama curl -fsSL https://ollama.com/install.sh | sh 下载太慢&#xff0c;使用讯雷&#xff0c;mac版下载链接 https://ollama.com/download/Ollama-darwin.zip 进入网站 deepseek-r1:8b&#xff0c;看内存大小4G就8B模型 …

VSCode设置内容字体大小

1、打开VSCode软件&#xff0c;点击左下角的“图标”&#xff0c;选择“Setting”。 在命令面板中的Font Size处选择适合自己的字体大小。 2、对比Font Size值为14与20下的字体大小。

嵌入式学习---蜂鸣器篇

1. 蜂鸣器分类 蜂鸣器是一种电子发声器件&#xff0c;采用直流电压供电&#xff0c;能够发出声音。广泛应用于计算机、打印机、报警器、电子玩具等电子产品中作为发声部件。一般仅从外形不易分辨蜂鸣器的种类。但是有些蜂鸣器使用广泛&#xff0c;见得多了就很容易分辨。例如常…

解析PHP文件路径相关常量

PHP文件路径相关常量包括以下几个常量&#xff1a; __FILE__&#xff1a;表示当前文件的绝对路径&#xff0c;包括文件名。 __DIR__&#xff1a;表示当前文件所在的目录的绝对路径&#xff0c;不包括文件名。 dirname(__FILE__)&#xff1a;等同于__DIR__&#xff0c;表示当前…

C++底层学习预备:模板初阶

文章目录 1.编程范式2.函数模板2.1 函数模板概念2.2 函数模板原理2.3 函数模板实例化2.3.1 隐式实例化2.3.2 显式实例化 2.4 模板参数的匹配原则 3.类模板希望读者们多多三连支持小编会继续更新你们的鼓励就是我前进的动力&#xff01; 进入STL库学习之前我们要先了解有关模板的…

【腾讯前端面试】纯css画图形

之前参加腾讯面试&#xff0c;第一轮是笔试&#xff0c;面试官发的试卷里有一题手写css画一个扇形、一个平行四边形……笔试时间还是比较充裕的&#xff0c;但是我对这题完全没有思路&#x1f62d;于是就空着了&#xff0c;最后也没过。 今天偶然翻到廖雪峰大佬的博客里提到了关…

智慧园区综合管理系统如何实现多个维度的高效管理与安全风险控制

内容概要 在当前快速发展的城市环境中&#xff0c;智慧园区综合管理系统正在成为各类园区管理的重要工具&#xff0c;无论是工业园、产业园、物流园&#xff0c;还是写字楼与公寓&#xff0c;都在积极寻求如何提升管理效率和保障安全。通过快鲸智慧园区管理系统&#xff0c;用…

自制虚拟机(C/C++)(三、做成标准GUI Windows软件,扩展指令集,直接支持img软盘)

开源地址:VMwork 要使终端不弹出&#xff0c; #pragma comment(linker, "/subsystem:windows /ENTRY:mainCRTStartup") 还要实现jmp near 0x01类似的 本次的main.cpp #include <graphics.h> #include <conio.h> #include <windows.h> #includ…

如何确认Linux嵌入式系统的触摸屏对应的是哪个设备文件(/dev/input/event1)?如何查看系统中所有的输入设备?输入设备的设备文件有什么特点?

Linux嵌入式系统的输入设备的设备文件有什么特点&#xff1f; 在 Linux 中&#xff0c;所有的输入设备&#xff08;如键盘、鼠标、触摸屏等&#xff09;都会被内核识别为 输入事件设备&#xff0c;并在 /dev/input/ 目录下创建相应的 设备文件&#xff0c;通常是&#xff1a; …

HTTP异步Client源码解析

我们知道Netty作为高性能通信框架&#xff0c;优点在于内部封装了管道的连接通信等操作&#xff0c;用户只需要调用封装好的接口&#xff0c;便可以很便捷的进行高并发通信。类似&#xff0c;在Http请求时&#xff0c;我们通过调用HttpClient&#xff0c;内部使用java NIO技术&…

利用Vue和javascript分别编写一个“Hello World”的定时更新

目录 一、利用Vue编写一个“Hello World”的定时更新&#xff08;1&#xff09;vue编码在Html文件中&#xff08;2&#xff09;vue编码在js文件中 二、利用javascript编写一个“Hello World”的定时更新 一、利用Vue编写一个“Hello World”的定时更新 &#xff08;1&#xff…

leetcode27.删除有序数组中的重复项

目录 问题描述判题标准示例提示 具体思路思路一思路二 代码实现 问题描述 给你一个非严格递增排列的数组nums&#xff0c;请你原地删除重复出现的元素&#xff0c;使每个元素只出现一次&#xff0c;返回删除后数组的新长度。元素的相对顺序应该保持一致 。然后返回nums中唯一元…