Commit 7b449b81e7be2671446a94a74c9c539f6c9be2a8

Authored by puhui999
1 parent 69a27b1e

【功能新增】IoT: 新增 RabbitMQ 数据桥梁实现

yudao-dependencies/pom.xml
... ... @@ -36,6 +36,7 @@
36 36 <!-- 消息队列 -->
37 37 <rocketmq-spring.version>2.3.2</rocketmq-spring.version>
38 38 <kafka-spring.version>3.3.3</kafka-spring.version>
  39 + <rabbitmq-spring.version>3.4.3</rabbitmq-spring.version>
39 40 <!-- 服务保障相关 -->
40 41 <lock4j.version>2.2.7</lock4j.version>
41 42 <!-- 监控相关 -->
... ... @@ -296,6 +297,12 @@
296 297 <artifactId>spring-kafka</artifactId>
297 298 <version>${kafka-spring.version}</version>
298 299 </dependency>
  300 + <dependency>
  301 + <groupId>org.springframework.boot</groupId>
  302 + <artifactId>spring-boot-starter-amqp</artifactId>
  303 + <version>${rabbitmq-spring.version}</version>
  304 + </dependency>
  305 +
299 306 <!-- 服务保障相关 -->
300 307 <dependency>
301 308 <groupId>cn.iocoder.boot</groupId>
... ...
yudao-module-iot/yudao-module-iot-biz/pom.xml
... ... @@ -86,6 +86,11 @@
86 86 <artifactId>spring-kafka</artifactId>
87 87 <optional>true</optional>
88 88 </dependency>
  89 + <dependency>
  90 + <groupId>org.springframework.boot</groupId>
  91 + <artifactId>spring-boot-starter-amqp</artifactId>
  92 + <optional>true</optional>
  93 + </dependency>
89 94  
90 95 <dependency>
91 96 <groupId>org.pf4j</groupId> <!-- PF4J:内置插件机制 -->
... ...
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/rule/IotDataBridgeDO.java
... ... @@ -204,4 +204,45 @@ public class IotDataBridgeDO extends BaseDO {
204 204  
205 205 }
206 206  
  207 + /**
  208 + * RabbitMQ 配置
  209 + */
  210 + @Data
  211 + public static class RabbitMQConfig implements Config {
  212 +
  213 + /**
  214 + * RabbitMQ 服务器地址
  215 + */
  216 + private String host;
  217 + /**
  218 + * 端口
  219 + */
  220 + private Integer port;
  221 + /**
  222 + * 虚拟主机
  223 + */
  224 + private String virtualHost;
  225 + /**
  226 + * 用户名
  227 + */
  228 + private String username;
  229 + /**
  230 + * 密码
  231 + */
  232 + private String password;
  233 +
  234 + /**
  235 + * 交换机名称
  236 + */
  237 + private String exchange;
  238 + /**
  239 + * 路由键
  240 + */
  241 + private String routingKey;
  242 + /**
  243 + * 队列名称
  244 + */
  245 + private String queue;
  246 + }
  247 +
207 248 }
... ...
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/action/databridge/IotRabbitMQDataBridgeExecute.java 0 → 100644
  1 +package cn.iocoder.yudao.module.iot.service.rule.action.databridge;
  2 +
  3 +import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotDataBridgeDO;
  4 +import cn.iocoder.yudao.module.iot.enums.rule.IotDataBridgTypeEnum;
  5 +import cn.iocoder.yudao.module.iot.mq.message.IotDeviceMessage;
  6 +import com.rabbitmq.client.Channel;
  7 +import com.rabbitmq.client.Connection;
  8 +import com.rabbitmq.client.ConnectionFactory;
  9 +import lombok.extern.slf4j.Slf4j;
  10 +import org.springframework.stereotype.Component;
  11 +
  12 +import java.nio.charset.StandardCharsets;
  13 +import java.time.LocalDateTime;
  14 +
  15 +/**
  16 + * RabbitMQ 的 {@link IotDataBridgeExecute} 实现类
  17 + *
  18 + * @author HUIHUI
  19 + */
  20 +@Component
  21 +@Slf4j
  22 +public class IotRabbitMQDataBridgeExecute extends AbstractCacheableDataBridgeExecute {
  23 +
  24 + @Override
  25 + public void execute(IotDeviceMessage message, IotDataBridgeDO dataBridge) {
  26 + // 1.1 校验数据桥梁的类型 == RABBITMQ
  27 + if (!IotDataBridgTypeEnum.RABBITMQ.getType().equals(dataBridge.getType())) {
  28 + return;
  29 + }
  30 + // 1.2 执行 RabbitMQ 发送消息
  31 + executeRabbitMQ(message, (IotDataBridgeDO.RabbitMQConfig) dataBridge.getConfig());
  32 + }
  33 +
  34 + private void executeRabbitMQ(IotDeviceMessage message, IotDataBridgeDO.RabbitMQConfig config) {
  35 + try {
  36 + // 1. 获取或创建 Channel
  37 + Channel channel = (Channel) getProducer(config);
  38 +
  39 + // 2.1 声明交换机、队列和绑定关系
  40 + channel.exchangeDeclare(config.getExchange(), "direct", true);
  41 + channel.queueDeclare(config.getQueue(), true, false, false, null);
  42 + channel.queueBind(config.getQueue(), config.getExchange(), config.getRoutingKey());
  43 +
  44 + // 2.2 发送消息
  45 + channel.basicPublish(config.getExchange(), config.getRoutingKey(), null,
  46 + message.toString().getBytes(StandardCharsets.UTF_8));
  47 + log.info("[executeRabbitMQ][message({}) config({}) 发送成功]", message, config);
  48 + } catch (Exception e) {
  49 + log.error("[executeRabbitMQ][message({}) config({}) 发送异常]", message, config, e);
  50 + }
  51 + }
  52 +
  53 + @Override
  54 + protected Object initProducer(Object config) throws Exception {
  55 + IotDataBridgeDO.RabbitMQConfig rabbitConfig = (IotDataBridgeDO.RabbitMQConfig) config;
  56 +
  57 + // 1. 创建连接工厂
  58 + ConnectionFactory factory = new ConnectionFactory();
  59 + factory.setHost(rabbitConfig.getHost());
  60 + factory.setPort(rabbitConfig.getPort());
  61 + factory.setVirtualHost(rabbitConfig.getVirtualHost());
  62 + factory.setUsername(rabbitConfig.getUsername());
  63 + factory.setPassword(rabbitConfig.getPassword());
  64 +
  65 + // 2. 创建连接
  66 + Connection connection = factory.newConnection();
  67 +
  68 + // 3. 创建信道
  69 + return connection.createChannel();
  70 + }
  71 +
  72 + @Override
  73 + protected void closeProducer(Object producer) {
  74 + if (producer instanceof Channel) {
  75 + try {
  76 + Channel channel = (Channel) producer;
  77 + if (channel.isOpen()) {
  78 + channel.close();
  79 + }
  80 + Connection connection = channel.getConnection();
  81 + if (connection.isOpen()) {
  82 + connection.close();
  83 + }
  84 + } catch (Exception e) {
  85 + log.error("[closeProducer][关闭 RabbitMQ 连接异常]", e);
  86 + }
  87 + }
  88 + }
  89 +
  90 + // TODO @芋道源码:测试代码,后续清理
  91 + public static void main(String[] args) {
  92 + // 1. 创建一个共享的实例
  93 + IotRabbitMQDataBridgeExecute action = new IotRabbitMQDataBridgeExecute();
  94 +
  95 + // 2. 创建共享的配置
  96 + IotDataBridgeDO.RabbitMQConfig config = new IotDataBridgeDO.RabbitMQConfig();
  97 + config.setHost("localhost");
  98 + config.setPort(5672);
  99 + config.setVirtualHost("/");
  100 + config.setUsername("admin");
  101 + config.setPassword("123456");
  102 + config.setExchange("test-exchange");
  103 + config.setRoutingKey("test-key");
  104 + config.setQueue("test-queue");
  105 +
  106 + // 3. 创建共享的消息
  107 + IotDeviceMessage message = IotDeviceMessage.builder()
  108 + .requestId("TEST-001")
  109 + .productKey("testProduct")
  110 + .deviceName("testDevice")
  111 + .deviceKey("testDeviceKey")
  112 + .type("property")
  113 + .identifier("temperature")
  114 + .data("{\"value\": 60}")
  115 + .reportTime(LocalDateTime.now())
  116 + .tenantId(1L)
  117 + .build();
  118 +
  119 + // 4. 执行两次测试,验证缓存
  120 + log.info("[main][第一次执行,应该会创建新的 channel]");
  121 + action.executeRabbitMQ(message, config);
  122 +
  123 + log.info("[main][第二次执行,应该会复用缓存的 channel]");
  124 + action.executeRabbitMQ(message, config);
  125 + }
  126 +}
... ...