Commit c6b58b0ebfbfdac305f8ae9d32de6156faba8131

Authored by YunaiV
1 parent 6a1798bf

【代码评审】IoT:数据桥梁实现

yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/action/databridge/AbstractCacheableDataBridgeExecute.java
... ... @@ -7,12 +7,7 @@ import lombok.extern.slf4j.Slf4j;
7 7  
8 8 import java.time.Duration;
9 9  
10   -// TODO @芋艿:因为下面的,都是有状态的,所以通过 guava 缓存连接,然后通过 RemovalNotification 实现关闭。例如说,一次新建有效期是 10 分钟;
11   -// TODO @芋艿:mq-redis
12   -// TODO @芋艿:mq-数据库
13   -// TODO @芋艿:kafka
14   -// TODO @芋艿:rocketmq
15   -// TODO @芋艿:rabbitmq
  10 +// TODO @芋艿:数据库
16 11 // TODO @芋艿:mqtt
17 12 // TODO @芋艿:tcp
18 13 // TODO @芋艿:websocket
... ... @@ -25,6 +20,7 @@ import java.time.Duration;
25 20 @Slf4j
26 21 public abstract class AbstractCacheableDataBridgeExecute implements IotDataBridgeExecute {
27 22  
  23 + // TODO @huihui:AbstractCacheableDataBridgeExecute<Producer> 这样,下面的 Object, Object 就有了类型;另外 IotDataBridgeDO.Config 可以替代一个 Object 哇,
28 24 /**
29 25 * Producer 缓存
30 26 */
... ... @@ -43,12 +39,14 @@ public abstract class AbstractCacheableDataBridgeExecute implements IotDataBridg
43 39 }
44 40 })
45 41 .build(new CacheLoader<Object, Object>() {
  42 +
46 43 @Override
47 44 public Object load(Object config) throws Exception {
48 45 Object producer = initProducer(config);
49 46 log.info("[PRODUCER_CACHE][配置({}) 对应的 producer 已创建并启动]", config);
50 47 return producer;
51 48 }
  49 +
52 50 });
53 51  
54 52 /**
... ... @@ -77,4 +75,4 @@ public abstract class AbstractCacheableDataBridgeExecute implements IotDataBridg
77 75 */
78 76 protected abstract void closeProducer(Object producer);
79 77  
80   -}
81 78 \ No newline at end of file
  79 +}
82 80 \ No newline at end of file
... ...
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/action/databridge/IotDataBridgeExecute.java
... ... @@ -11,6 +11,8 @@ import cn.iocoder.yudao.module.iot.mq.message.IotDeviceMessage;
11 11 */
12 12 public interface IotDataBridgeExecute {
13 13  
  14 + // TODO @huihui:要不搞个 getType?然后 execute0 由子类实现。这样,子类的 executeRedisStream ,其实就是 execute0 了。
  15 +
14 16 /**
15 17 * 执行数据桥梁操作
16 18 *
... ...
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/action/databridge/IotKafkaMQDataBridgeExecute.java
... ... @@ -10,6 +10,7 @@ import org.springframework.kafka.core.DefaultKafkaProducerFactory;
10 10 import org.springframework.kafka.core.KafkaTemplate;
11 11 import org.springframework.stereotype.Component;
12 12  
  13 +import java.time.Duration;
13 14 import java.time.LocalDateTime;
14 15 import java.util.HashMap;
15 16 import java.util.Map;
... ... @@ -25,13 +26,15 @@ import java.util.concurrent.TimeoutException;
25 26 @Slf4j
26 27 public class IotKafkaMQDataBridgeExecute extends AbstractCacheableDataBridgeExecute {
27 28  
  29 + private static final Duration SEND_TIMEOUT = Duration.ofMillis(10);
  30 +
28 31 @Override
29 32 public void execute(IotDeviceMessage message, IotDataBridgeDO dataBridge) {
30   - // 1.1 校验数据桥梁的类型 == KAFKA
  33 + // 1. 校验数据桥梁的类型 == KAFKA
31 34 if (!IotDataBridgTypeEnum.KAFKA.getType().equals(dataBridge.getType())) {
32 35 return;
33 36 }
34   - // 1.2 执行 Kafka 发送消息
  37 + // 2. 执行 Kafka 发送消息
35 38 executeKafka(message, (IotDataBridgeDO.KafkaMQConfig) dataBridge.getConfig());
36 39 }
37 40  
... ... @@ -43,7 +46,7 @@ public class IotKafkaMQDataBridgeExecute extends AbstractCacheableDataBridgeExec
43 46  
44 47 // 2. 发送消息并等待结果
45 48 kafkaTemplate.send(config.getTopic(), message.toString())
46   - .get(10, TimeUnit.SECONDS); // 添加超时等待
  49 + .get(SEND_TIMEOUT.getSeconds(), TimeUnit.SECONDS); // 添加超时等待
47 50 log.info("[executeKafka][message({}) 发送成功]", message);
48 51 } catch (TimeoutException e) {
49 52 log.error("[executeKafka][message({}) config({}) 发送超时]", message, config, e);
... ... @@ -55,13 +58,12 @@ public class IotKafkaMQDataBridgeExecute extends AbstractCacheableDataBridgeExec
55 58 @Override
56 59 protected Object initProducer(Object config) {
57 60 IotDataBridgeDO.KafkaMQConfig kafkaConfig = (IotDataBridgeDO.KafkaMQConfig) config;
58   -
  61 +
59 62 // 1.1 构建生产者配置
60 63 Map<String, Object> props = new HashMap<>();
61 64 props.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, kafkaConfig.getBootstrapServers());
62 65 props.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class);
63 66 props.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, StringSerializer.class);
64   -
65 67 // 1.2 如果配置了认证信息
66 68 if (kafkaConfig.getUsername() != null && kafkaConfig.getPassword() != null) {
67 69 props.put("security.protocol", "SASL_PLAINTEXT");
... ... @@ -70,7 +72,6 @@ public class IotKafkaMQDataBridgeExecute extends AbstractCacheableDataBridgeExec
70 72 "org.apache.kafka.common.security.plain.PlainLoginModule required username=\""
71 73 + kafkaConfig.getUsername() + "\" password=\"" + kafkaConfig.getPassword() + "\";");
72 74 }
73   -
74 75 // 1.3 如果启用 SSL
75 76 if (Boolean.TRUE.equals(kafkaConfig.getSsl())) {
76 77 props.put("security.protocol", "SSL");
... ...
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/action/databridge/IotRabbitMQDataBridgeExecute.java
... ... @@ -51,6 +51,7 @@ public class IotRabbitMQDataBridgeExecute extends AbstractCacheableDataBridgeExe
51 51 }
52 52  
53 53 @Override
  54 + @SuppressWarnings("resource")
54 55 protected Object initProducer(Object config) throws Exception {
55 56 IotDataBridgeDO.RabbitMQConfig rabbitConfig = (IotDataBridgeDO.RabbitMQConfig) config;
56 57  
... ...
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/action/databridge/IotRedisStreamMQDataBridgeExecute.java
... ... @@ -42,6 +42,7 @@ public class IotRedisStreamMQDataBridgeExecute extends AbstractCacheableDataBrid
42 42 }
43 43  
44 44 @SuppressWarnings("unchecked")
  45 + // TODO @huihui:try catch 交给父类来做,子类不处理异常
45 46 private void executeRedisStream(IotDeviceMessage message, IotDataBridgeDO.RedisStreamMQConfig config) {
46 47 try {
47 48 // 1. 获取 RedisTemplate
... ... @@ -71,6 +72,7 @@ public class IotRedisStreamMQDataBridgeExecute extends AbstractCacheableDataBrid
71 72 serverConfig.setPassword(redisConfig.getPassword());
72 73 }
73 74  
  75 + // TODO @huihui:看看能不能简化一些。按道理说,不用这么多的哈。
74 76 // 2.1 创建 RedissonClient
75 77 RedissonClient redisson = Redisson.create(redissonConfig);
76 78 // 2.2 创建并配置 RedisTemplate
... ... @@ -89,6 +91,7 @@ public class IotRedisStreamMQDataBridgeExecute extends AbstractCacheableDataBrid
89 91  
90 92 @Override
91 93 protected void closeProducer(Object producer) {
  94 + // TODO @huihui:try catch 交给父类来做。子类不处理异常
92 95 if (producer instanceof RedisTemplate) {
93 96 RedisConnectionFactory factory = ((RedisTemplate<?, ?>) producer).getConnectionFactory();
94 97 try {
... ... @@ -101,7 +104,7 @@ public class IotRedisStreamMQDataBridgeExecute extends AbstractCacheableDataBrid
101 104 }
102 105 }
103 106  
104   -
  107 + // TODO @huihui:看看能不能简化一些。按道理说,不用这么多的哈。
105 108 public static RedisSerializer<?> buildRedisSerializer() {
106 109 RedisSerializer<Object> json = RedisSerializer.json();
107 110 // 解决 LocalDateTime 的序列化
... ...