1. 依赖/配置
依赖
<!-- MQTT -->
<dependency>
<groupId>org.eclipse.paho</groupId>
<artifactId>org.eclipse.paho.client.mqttv3</artifactId>
<version>1.2.5</version>
</dependency>
<!--kafka-->
<dependency>
<groupId>org.springframework.kafka</groupId>
<artifactId>spring-kafka</artifactId>
</dependency>
配置
spring:
main:
allow-circular-references: true #允许循环依赖,如果有这个情况的话
kafka:
bootstrap-servers: localhost:9092 #kafka地址
# ----MQTT
customer:
mqtt:
broker: tcp://localhost:1883
clientId: nays_service #发布客户端ID
userName: admin
password: public
2. 订阅/发布
2.1 Kafka
消息生产者
package com.jdck.msg.kafka;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Component;
import java.util.concurrent.ExecutionException;
/**
* 创建消息生产者
*
* @author gongjp
* @since 2024/8/21 13:42
*/
@Component
@Slf4j
public class KafkaProducer {
@Resource
private KafkaTemplate<String, Object> kafkaTemplate;
public static final String TOPIC_TEST = "kafka-test";
public static final String TOPIC_GROUP = "test-consumer-group";
public void send(Object obj) throws ExecutionException, InterruptedException {
// 发送消息
kafkaTemplate.send(TOPIC_TEST, obj);
log.info("【Kafka】--[{}]<发送>消息{}",TOPIC_TEST ,obj);
}
}
消息消费者
package com.jdck.msg.kafka;
import lombok.extern.slf4j.Slf4j;
import org.springframework.kafka.annotation.KafkaListener;
import org.springframework.stereotype.Component;
/**
* 创建消息消费者
*
* @author gongjp
* @since 2024/8/21 13:44
*/
@Component
@Slf4j
public class KafkaConsumer {
@KafkaListener(topics = KafkaProducer.TOPIC_TEST, groupId = KafkaProducer.TOPIC_GROUP)
public void topicTest(String message) {
log.info("【Kafka】--[{}]<接收>消息{}", KafkaProducer.TOPIC_TEST, message);
}
}
2.2 MQTT
配置类(构建客户端)
package com.jdck.msg.mqtt;
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* MQTT配置类
*
* @author gongjp
* @since 2024/8/21 14:38
*/
@Configuration
public class MqttConfig {
// 使用@Value注解从配置文件读取MQTT服务器的URL
@Value("${customer.mqtt.url:tcp://localhost:1883}")
private String url;
// 客户端ID,通常每个客户端应该有一个唯一的ID
@Value("${customer.mqtt.clientId:SpringBootMqttClient}")
private String clientId;
// 用户名和密码(可选)
@Value("${customer.mqtt.username:}")
private String username;
@Value("${customer.mqtt.password:}")
private String password;
// 创建一个MqttClient的Bean,这样它就可以被Spring容器管理
@Bean
public MqttClient mqttClient() throws Exception {
// 创建MqttClient实例
MqttClient client = new MqttClient(url, clientId);
// 设置连接选项
MqttConnectOptions connOpts = new MqttConnectOptions();
connOpts.setCleanSession(true); // 清理会话
// 如果提供了用户名和密码,则设置它们
if (username != null && password != null) {
connOpts.setUserName(username);
connOpts.setPassword(password.toCharArray());
}
// 连接到MQTT服务器
client.connect(connOpts);
return client;
}
}
发布
package com.jdck.msg.mqtt;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* 消息发布
*
* @author gongjp
* @since 2024/8/21 14:40
*/
// 标记这是一个服务类
@Service
@Slf4j
public class MqttPublisher {
// 自动注入MqttClient的Bean
@Autowired
private MqttClient mqttClient;
// 定义一个方法来发送MQTT消息
public void publish(String topic, String payload) throws Exception {
// 创建一个MqttMessage实例,设置消息内容
MqttMessage message = new MqttMessage(payload.getBytes());
// 发送消息到指定的主题
mqttClient.publish(topic, message);
log.info("【MQTT】--[{}]<发送>消息:{}",topic,message);
}
}
接收消息
package com.jdck.msg.mqtt;
import com.jdck.msg.kafka.KafkaProducer;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.PreDestroy;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.paho.client.mqttv3.*;
import org.springframework.stereotype.Component;
/**
* XXX
*
* @author gongjp
* @since 2024/8/21 14:57
*/
@Slf4j
@Component
@RequiredArgsConstructor
public class MqttSubscriber implements MqttCallback {
private final MqttClient mqttClient;
private final KafkaProducer kafkaProducer;
/**
* 应用启动时订阅MQTT主题
*
* @throws MqttException 如果订阅过程中发生异常
*/
@PostConstruct
public void start() throws MqttException {
mqttClient.setCallback(this);
mqttClient.subscribe("mqtt/receive");
}
/**
* 应用关闭时断开MQTT连接(可选)
*
* @throws MqttException 如果断开连接过程中发生异常
*/
@PreDestroy
public void stop() throws MqttException {
mqttClient.disconnect();
}
/**
* 连接丢失时的处理逻辑
* @param throwable
*/
@Override
public void connectionLost(Throwable throwable) {
}
/**
* 处理接收到的消息
* @param topic topic
* @param mqttMessage 消息
* @throws Exception
*/
@Override
public void messageArrived(String topic, MqttMessage mqttMessage) throws Exception {
log.info("【MQTT】--[{}]<接收>消息:{}",topic,mqttMessage);
//接收到消息再发送到kafka
kafkaProducer.send(mqttMessage.toString());
}
@Override
public void deliveryComplete(IMqttDeliveryToken iMqttDeliveryToken) {
}
}
3. 测试
3.1 Controller
package com.jdck.msg.controller;
import com.jdck.msg.kafka.KafkaProducer;
import com.jdck.msg.mqtt.MqttPublisher;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 测试服务类
*
* @author gongjp
* @since 2024/8/21 10:03
*/
@RestController
@Slf4j
@RequiredArgsConstructor
public class SendController {
private final MqttPublisher mqttPublisher;
private final KafkaProducer kafkaProducer; // 注意使用自己创建的,看清楚!
/**
* 发送mqtt信息
* @param topic 要发到哪一个主题
* @param msg 发送的消息
* @return
*/
@RequestMapping("/send/mqtt")
public String sendMessageByMqtt(String topic,String msg){
try {
mqttPublisher.publish(topic,msg);
return "发送成功";
} catch (Exception e) {
log.error("发送失败",e);
return "发送失败";
}
}
/**
* 发送Kafka消息
*
* @param msg
* @return
*/
@RequestMapping("/send/kafka")
public String sendMessageByKafka(String msg){
try {
kafkaProducer.send(msg);
return "发送成功";
} catch (Exception e) {
log.error("发送失败",e);
return "发送失败";
}
}
}
3.2 MQTTX
使用mqtt建立连接然后发送信息到指定的topic
4. 参考/安装教程
4.1. MQTT
- springboot集成mqtt
4.2 Kafka
- kafka安装
kafka 安装、配置、启动、测试说明:
1. 安装:直接官网下载安装包,解压到指定位置即可(kafka 依赖的 Zookeeper 在文件中已包含)
下载地址:https://kafka.apache.org/downloads
示例版本:kafka_2.13-2.8.0.tgz
下载后可本地解压安装,解压位置自选,如 D:\Java 下
解压命令:tar -zxvf kafka_2.13-2.8.0.tgz
PS:可在 idea 命令行窗口或 git 提供的命令窗口中进行命令操作
使用 git 提供的命令窗口:空白文件夹中右键——》Git Bash Here 即可打开
2. 添加地址配置
在 D:\Java\kafka_2.13-2.8.0\config\server.properties 中搜索添加以下两行配置:
listeners=PLAINTEXT://localhost:9092
advertised.listeners=PLAINTEXT://localhost:9092
说明:以上配置默认是注释掉的,可搜索找到,根据需求进行自定义地址配置
- Kafka的使用(Windows中)