Commit 27e08266e085064dbf07bda0cee6b0aff3eddb50

Authored by 芋道源码
Committed by Gitee
2 parents 569d6514 cdf316e7

!1269 【代码优化】IoT: 优化数据桥梁

Merge pull request !1269 from puhui999/iot
Showing 30 changed files with 858 additions and 470 deletions
yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/DictTypeConstants.java
@@ -15,5 +15,7 @@ public class DictTypeConstants { @@ -15,5 +15,7 @@ public class DictTypeConstants {
15 public static final String VALIDATE_TYPE = "iot_validate_type"; 15 public static final String VALIDATE_TYPE = "iot_validate_type";
16 16
17 public static final String DEVICE_STATE = "iot_device_state"; 17 public static final String DEVICE_STATE = "iot_device_state";
  18 + public static final String IOT_DATA_BRIDGE_DIRECTION_ENUM = "iot_data_bridge_direction_enum";
  19 + public static final String IOT_DATA_BRIDGE_TYPE_ENUM = "iot_data_bridge_type_enum";
18 20
19 } 21 }
yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/ErrorCodeConstants.java
@@ -70,4 +70,7 @@ public interface ErrorCodeConstants { @@ -70,4 +70,7 @@ public interface ErrorCodeConstants {
70 // ========== MQTT 通信相关 1-050-009-000 ========== 70 // ========== MQTT 通信相关 1-050-009-000 ==========
71 ErrorCode MQTT_TOPIC_ILLEGAL = new ErrorCode(1_050_009_000, "topic illegal"); 71 ErrorCode MQTT_TOPIC_ILLEGAL = new ErrorCode(1_050_009_000, "topic illegal");
72 72
  73 + // ========== IoT 数据桥梁 1-050-010-000 ==========
  74 + ErrorCode DATA_BRIDGE_NOT_EXISTS = new ErrorCode(1_050_010_000, "IoT 数据桥梁不存在");
  75 +
73 } 76 }
74 \ No newline at end of file 77 \ No newline at end of file
yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/rule/IotDataBridgDirectionEnum.java renamed to yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/rule/IotDataBridgeDirectionEnum.java
@@ -13,14 +13,14 @@ import java.util.Arrays; @@ -13,14 +13,14 @@ import java.util.Arrays;
13 */ 13 */
14 @RequiredArgsConstructor 14 @RequiredArgsConstructor
15 @Getter 15 @Getter
16 -public enum IotDataBridgDirectionEnum implements ArrayValuable<Integer> { 16 +public enum IotDataBridgeDirectionEnum implements ArrayValuable<Integer> {
17 17
18 INPUT(1), // 输入 18 INPUT(1), // 输入
19 OUTPUT(2); // 输出 19 OUTPUT(2); // 输出
20 20
21 private final Integer type; 21 private final Integer type;
22 22
23 - public static final Integer[] ARRAYS = Arrays.stream(values()).map(IotDataBridgDirectionEnum::getType).toArray(Integer[]::new); 23 + public static final Integer[] ARRAYS = Arrays.stream(values()).map(IotDataBridgeDirectionEnum::getType).toArray(Integer[]::new);
24 24
25 @Override 25 @Override
26 public Integer[] array() { 26 public Integer[] array() {
yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/rule/IotDataBridgTypeEnum.java renamed to yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/rule/IotDataBridgeTypeEnum.java
@@ -13,25 +13,26 @@ import java.util.Arrays; @@ -13,25 +13,26 @@ import java.util.Arrays;
13 */ 13 */
14 @RequiredArgsConstructor 14 @RequiredArgsConstructor
15 @Getter 15 @Getter
16 -public enum IotDataBridgTypeEnum implements ArrayValuable<Integer> { 16 +public enum IotDataBridgeTypeEnum implements ArrayValuable<Integer> {
17 17
18 - HTTP(1),  
19 - TCP(2),  
20 - WEBSOCKET(3), 18 + HTTP(1, "HTTP"),
  19 + TCP(2, "TCP"),
  20 + WEBSOCKET(3, "WEBSOCKET"),
21 21
22 - MQTT(10), 22 + MQTT(10, "MQTT"),
23 23
24 - DATABASE(20),  
25 - REDIS_STREAM(21), 24 + DATABASE(20, "DATABASE"),
  25 + REDIS_STREAM(21, "REDIS_STREAM"),
26 26
27 - ROCKETMQ(30),  
28 - RABBITMQ(31),  
29 - KAFKA(32)  
30 - ; 27 + ROCKETMQ(30, "ROCKETMQ"),
  28 + RABBITMQ(31, "RABBITMQ"),
  29 + KAFKA(32, "KAFKA");
31 30
32 private final Integer type; 31 private final Integer type;
33 32
34 - public static final Integer[] ARRAYS = Arrays.stream(values()).map(IotDataBridgTypeEnum::getType).toArray(Integer[]::new); 33 + private final String name;
  34 +
  35 + public static final Integer[] ARRAYS = Arrays.stream(values()).map(IotDataBridgeTypeEnum::getType).toArray(Integer[]::new);
35 36
36 @Override 37 @Override
37 public Integer[] array() { 38 public Integer[] array() {
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/rule/IotDataBridgeController.java 0 → 100644
  1 +package cn.iocoder.yudao.module.iot.controller.admin.rule;
  2 +
  3 +import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
  4 +import cn.iocoder.yudao.framework.common.pojo.CommonResult;
  5 +import cn.iocoder.yudao.framework.common.pojo.PageParam;
  6 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  7 +import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
  8 +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
  9 +import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.databridge.IotDataBridgePageReqVO;
  10 +import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.databridge.IotDataBridgeRespVO;
  11 +import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.databridge.IotDataBridgeSaveReqVO;
  12 +import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotDataBridgeDO;
  13 +import cn.iocoder.yudao.module.iot.service.rule.IotDataBridgeService;
  14 +import io.swagger.v3.oas.annotations.Operation;
  15 +import io.swagger.v3.oas.annotations.Parameter;
  16 +import io.swagger.v3.oas.annotations.tags.Tag;
  17 +import jakarta.annotation.Resource;
  18 +import jakarta.servlet.http.HttpServletResponse;
  19 +import jakarta.validation.Valid;
  20 +import org.springframework.security.access.prepost.PreAuthorize;
  21 +import org.springframework.validation.annotation.Validated;
  22 +import org.springframework.web.bind.annotation.*;
  23 +
  24 +import java.io.IOException;
  25 +import java.util.List;
  26 +
  27 +import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
  28 +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
  29 +
  30 +@Tag(name = "管理后台 - IoT 数据桥梁")
  31 +@RestController
  32 +@RequestMapping("/iot/data-bridge")
  33 +@Validated
  34 +public class IotDataBridgeController {
  35 +
  36 + @Resource
  37 + private IotDataBridgeService dataBridgeService;
  38 +
  39 + @PostMapping("/create")
  40 + @Operation(summary = "创建IoT 数据桥梁")
  41 + @PreAuthorize("@ss.hasPermission('iot:data-bridge:create')")
  42 + public CommonResult<Long> createDataBridge(@Valid @RequestBody IotDataBridgeSaveReqVO createReqVO) {
  43 + return success(dataBridgeService.createDataBridge(createReqVO));
  44 + }
  45 +
  46 + @PutMapping("/update")
  47 + @Operation(summary = "更新IoT 数据桥梁")
  48 + @PreAuthorize("@ss.hasPermission('iot:data-bridge:update')")
  49 + public CommonResult<Boolean> updateDataBridge(@Valid @RequestBody IotDataBridgeSaveReqVO updateReqVO) {
  50 + dataBridgeService.updateDataBridge(updateReqVO);
  51 + return success(true);
  52 + }
  53 +
  54 + @DeleteMapping("/delete")
  55 + @Operation(summary = "删除IoT 数据桥梁")
  56 + @Parameter(name = "id", description = "编号", required = true)
  57 + @PreAuthorize("@ss.hasPermission('iot:data-bridge:delete')")
  58 + public CommonResult<Boolean> deleteDataBridge(@RequestParam("id") Long id) {
  59 + dataBridgeService.deleteDataBridge(id);
  60 + return success(true);
  61 + }
  62 +
  63 + @GetMapping("/get")
  64 + @Operation(summary = "获得IoT 数据桥梁")
  65 + @Parameter(name = "id", description = "编号", required = true, example = "1024")
  66 + @PreAuthorize("@ss.hasPermission('iot:data-bridge:query')")
  67 + public CommonResult<IotDataBridgeRespVO> getDataBridge(@RequestParam("id") Long id) {
  68 + IotDataBridgeDO dataBridge = dataBridgeService.getDataBridge(id);
  69 + return success(BeanUtils.toBean(dataBridge, IotDataBridgeRespVO.class));
  70 + }
  71 +
  72 + @GetMapping("/page")
  73 + @Operation(summary = "获得IoT 数据桥梁分页")
  74 + @PreAuthorize("@ss.hasPermission('iot:data-bridge:query')")
  75 + public CommonResult<PageResult<IotDataBridgeRespVO>> getDataBridgePage(@Valid IotDataBridgePageReqVO pageReqVO) {
  76 + PageResult<IotDataBridgeDO> pageResult = dataBridgeService.getDataBridgePage(pageReqVO);
  77 + return success(BeanUtils.toBean(pageResult, IotDataBridgeRespVO.class));
  78 + }
  79 +
  80 + @GetMapping("/export-excel")
  81 + @Operation(summary = "导出IoT 数据桥梁 Excel")
  82 + @PreAuthorize("@ss.hasPermission('iot:data-bridge:export')")
  83 + @ApiAccessLog(operateType = EXPORT)
  84 + public void exportDataBridgeExcel(@Valid IotDataBridgePageReqVO pageReqVO,
  85 + HttpServletResponse response) throws IOException {
  86 + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
  87 + List<IotDataBridgeDO> list = dataBridgeService.getDataBridgePage(pageReqVO).getList();
  88 + // 导出 Excel
  89 + ExcelUtils.write(response, "IoT 数据桥梁.xls", "数据", IotDataBridgeRespVO.class,
  90 + BeanUtils.toBean(list, IotDataBridgeRespVO.class));
  91 + }
  92 +
  93 +}
0 \ No newline at end of file 94 \ No newline at end of file
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/rule/vo/databridge/IotDataBridgePageReqVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.iot.controller.admin.rule.vo.databridge;
  2 +
  3 +import cn.iocoder.yudao.framework.common.pojo.PageParam;
  4 +import io.swagger.v3.oas.annotations.media.Schema;
  5 +import lombok.Data;
  6 +import lombok.EqualsAndHashCode;
  7 +import lombok.ToString;
  8 +import org.springframework.format.annotation.DateTimeFormat;
  9 +
  10 +import java.time.LocalDateTime;
  11 +
  12 +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
  13 +
  14 +@Schema(description = "管理后台 - IoT 数据桥梁分页 Request VO")
  15 +@Data
  16 +@EqualsAndHashCode(callSuper = true)
  17 +@ToString(callSuper = true)
  18 +public class IotDataBridgePageReqVO extends PageParam {
  19 +
  20 + @Schema(description = "桥梁名称", example = "赵六")
  21 + private String name;
  22 +
  23 + @Schema(description = "桥梁描述", example = "随便")
  24 + private String description;
  25 +
  26 + @Schema(description = "桥梁状态", example = "2")
  27 + private Integer status;
  28 +
  29 + @Schema(description = "桥梁方向")
  30 + private Integer direction;
  31 +
  32 + @Schema(description = "桥梁类型", example = "1")
  33 + private Integer type;
  34 +
  35 + @Schema(description = "创建时间")
  36 + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
  37 + private LocalDateTime[] createTime;
  38 +
  39 +}
0 \ No newline at end of file 40 \ No newline at end of file
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/rule/vo/databridge/IotDataBridgeRespVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.iot.controller.admin.rule.vo.databridge;
  2 +
  3 +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
  4 +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
  5 +import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.databridge.config.IotDataBridgeConfig;
  6 +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
  7 +import com.alibaba.excel.annotation.ExcelProperty;
  8 +import io.swagger.v3.oas.annotations.media.Schema;
  9 +import lombok.Data;
  10 +
  11 +import java.time.LocalDateTime;
  12 +
  13 +import static cn.iocoder.yudao.module.iot.enums.DictTypeConstants.IOT_DATA_BRIDGE_DIRECTION_ENUM;
  14 +import static cn.iocoder.yudao.module.iot.enums.DictTypeConstants.IOT_DATA_BRIDGE_TYPE_ENUM;
  15 +import static cn.iocoder.yudao.module.system.enums.DictTypeConstants.COMMON_STATUS;
  16 +
  17 +@Schema(description = "管理后台 - IoT 数据桥梁 Response VO")
  18 +@Data
  19 +@ExcelIgnoreUnannotated
  20 +public class IotDataBridgeRespVO {
  21 +
  22 + @Schema(description = "桥梁编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "18564")
  23 + @ExcelProperty("桥梁编号")
  24 + private Long id;
  25 +
  26 + @Schema(description = "桥梁名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "赵六")
  27 + @ExcelProperty("桥梁名称")
  28 + private String name;
  29 +
  30 + @Schema(description = "桥梁描述", example = "随便")
  31 + @ExcelProperty("桥梁描述")
  32 + private String description;
  33 +
  34 + @Schema(description = "桥梁状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
  35 + @ExcelProperty(value = "桥梁状态", converter = DictConvert.class)
  36 + @DictFormat(COMMON_STATUS)
  37 + private Integer status;
  38 +
  39 + @Schema(description = "桥梁方向", requiredMode = Schema.RequiredMode.REQUIRED)
  40 + @ExcelProperty(value = "桥梁方向", converter = DictConvert.class)
  41 + @DictFormat(IOT_DATA_BRIDGE_DIRECTION_ENUM)
  42 + private Integer direction;
  43 +
  44 + @Schema(description = "桥梁类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
  45 + @ExcelProperty(value = "桥梁类型", converter = DictConvert.class)
  46 + @DictFormat(IOT_DATA_BRIDGE_TYPE_ENUM)
  47 + private Integer type;
  48 +
  49 + @Schema(description = "桥梁配置")
  50 + @ExcelProperty("桥梁配置")
  51 + private IotDataBridgeConfig config;
  52 +
  53 + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
  54 + @ExcelProperty("创建时间")
  55 + private LocalDateTime createTime;
  56 +
  57 +}
0 \ No newline at end of file 58 \ No newline at end of file
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/rule/vo/databridge/IotDataBridgeSaveReqVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.iot.controller.admin.rule.vo.databridge;
  2 +
  3 +import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.databridge.config.IotDataBridgeConfig;
  4 +import io.swagger.v3.oas.annotations.media.Schema;
  5 +import jakarta.validation.constraints.NotEmpty;
  6 +import jakarta.validation.constraints.NotNull;
  7 +import lombok.Data;
  8 +
  9 +@Schema(description = "管理后台 - IoT 数据桥梁新增/修改 Request VO")
  10 +@Data
  11 +public class IotDataBridgeSaveReqVO {
  12 +
  13 + @Schema(description = "桥梁编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "18564")
  14 + private Long id;
  15 +
  16 + @Schema(description = "桥梁名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "赵六")
  17 + @NotEmpty(message = "桥梁名称不能为空")
  18 + private String name;
  19 +
  20 + @Schema(description = "桥梁描述", example = "随便")
  21 + private String description;
  22 +
  23 + @Schema(description = "桥梁状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
  24 + @NotNull(message = "桥梁状态不能为空")
  25 + private Integer status;
  26 +
  27 + @Schema(description = "桥梁方向", requiredMode = Schema.RequiredMode.REQUIRED)
  28 + @NotNull(message = "桥梁方向不能为空")
  29 + private Integer direction;
  30 +
  31 + @Schema(description = "桥梁类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
  32 + @NotNull(message = "桥梁类型不能为空")
  33 + private Integer type;
  34 +
  35 + @Schema(description = "桥梁配置")
  36 + @NotNull(message = "桥梁配置不能为空")
  37 + private IotDataBridgeConfig config;
  38 +
  39 +}
0 \ No newline at end of file 40 \ No newline at end of file
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/rule/vo/databridge/config/IotDataBridgeConfig.java 0 → 100644
  1 +package cn.iocoder.yudao.module.iot.controller.admin.rule.vo.databridge.config;
  2 +
  3 +import com.fasterxml.jackson.annotation.JsonSubTypes;
  4 +import com.fasterxml.jackson.annotation.JsonTypeInfo;
  5 +import lombok.Data;
  6 +
  7 +/**
  8 + * 抽象类 IotDataBridgeConfig
  9 + *
  10 + * 用于表示数据桥梁配置数据的通用类型,根据具体的 "type" 字段动态映射到对应的子类。
  11 + * 提供多态支持,适用于不同类型的数据结构序列化和反序列化场景。
  12 + *
  13 + * @author HUIHUI
  14 + */
  15 +@Data
  16 +@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type", visible = true)
  17 +@JsonSubTypes({
  18 + @JsonSubTypes.Type(value = IotDataBridgeHttpConfig.class, name = "HTTP"),
  19 + @JsonSubTypes.Type(value = IotDataBridgeKafkaMQConfig.class, name = "KAFKA"),
  20 + @JsonSubTypes.Type(value = IotDataBridgeMqttConfig.class, name = "MQTT"),
  21 + @JsonSubTypes.Type(value = IotDataBridgeRabbitMQConfig.class, name = "RABBITMQ"),
  22 + @JsonSubTypes.Type(value = IotDataBridgeRedisStreamMQConfig.class, name = "REDIS_STREAM"),
  23 + @JsonSubTypes.Type(value = IotDataBridgeRocketMQConfig.class, name = "ROCKETMQ"),
  24 +})
  25 +public abstract class IotDataBridgeConfig {
  26 +
  27 + /**
  28 + * 配置类型
  29 + */
  30 + private String type;
  31 +
  32 +}
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/rule/vo/databridge/config/IotDataBridgeHttpConfig.java 0 → 100644
  1 +package cn.iocoder.yudao.module.iot.controller.admin.rule.vo.databridge.config;
  2 +
  3 +import lombok.Data;
  4 +
  5 +import java.util.Map;
  6 +
  7 +/**
  8 + * HTTP 配置
  9 + *
  10 + * @author HUIHUI
  11 + */
  12 +@Data
  13 +public class IotDataBridgeHttpConfig extends IotDataBridgeConfig {
  14 +
  15 + /**
  16 + * 请求 URL
  17 + */
  18 + private String url;
  19 + /**
  20 + * 请求方法
  21 + */
  22 + private String method;
  23 + /**
  24 + * 请求头
  25 + */
  26 + private Map<String, String> headers;
  27 + /**
  28 + * 请求参数
  29 + */
  30 + private Map<String, String> query;
  31 + /**
  32 + * 请求体
  33 + */
  34 + private String body;
  35 +
  36 +}
0 \ No newline at end of file 37 \ No newline at end of file
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/rule/vo/databridge/config/IotDataBridgeKafkaMQConfig.java 0 → 100644
  1 +package cn.iocoder.yudao.module.iot.controller.admin.rule.vo.databridge.config;
  2 +
  3 +import lombok.Data;
  4 +
  5 +/**
  6 + * Kafka 配置
  7 + *
  8 + * @author HUIHUI
  9 + */
  10 +@Data
  11 +public class IotDataBridgeKafkaMQConfig extends IotDataBridgeConfig {
  12 +
  13 + /**
  14 + * Kafka 服务器地址
  15 + */
  16 + private String bootstrapServers;
  17 + /**
  18 + * 用户名
  19 + */
  20 + private String username;
  21 + /**
  22 + * 密码
  23 + */
  24 + private String password;
  25 + /**
  26 + * 是否启用 SSL
  27 + */
  28 + private Boolean ssl;
  29 +
  30 + /**
  31 + * 主题
  32 + */
  33 + private String topic;
  34 +
  35 +}
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/rule/vo/databridge/config/IotDataBridgeMqttConfig.java 0 → 100644
  1 +package cn.iocoder.yudao.module.iot.controller.admin.rule.vo.databridge.config;
  2 +
  3 +import lombok.Data;
  4 +
  5 +/**
  6 + * MQTT 配置
  7 + *
  8 + * @author HUIHUI
  9 + */
  10 +@Data
  11 +public class IotDataBridgeMqttConfig extends IotDataBridgeConfig {
  12 +
  13 + /**
  14 + * MQTT 服务器地址
  15 + */
  16 + private String url;
  17 + /**
  18 + * 用户名
  19 + */
  20 + private String username;
  21 + /**
  22 + * 密码
  23 + */
  24 + private String password;
  25 + /**
  26 + * 客户端编号
  27 + */
  28 + private String clientId;
  29 + /**
  30 + * 主题
  31 + */
  32 + private String topic;
  33 +
  34 +}
0 \ No newline at end of file 35 \ No newline at end of file
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/rule/vo/databridge/config/IotDataBridgeRabbitMQConfig.java 0 → 100644
  1 +package cn.iocoder.yudao.module.iot.controller.admin.rule.vo.databridge.config;
  2 +
  3 +import lombok.Data;
  4 +
  5 +/**
  6 + * RabbitMQ 配置
  7 + *
  8 + * @author HUIHUI
  9 + */
  10 +@Data
  11 +public class IotDataBridgeRabbitMQConfig extends IotDataBridgeConfig {
  12 +
  13 + /**
  14 + * RabbitMQ 服务器地址
  15 + */
  16 + private String host;
  17 + /**
  18 + * 端口
  19 + */
  20 + private Integer port;
  21 + /**
  22 + * 虚拟主机
  23 + */
  24 + private String virtualHost;
  25 + /**
  26 + * 用户名
  27 + */
  28 + private String username;
  29 + /**
  30 + * 密码
  31 + */
  32 + private String password;
  33 +
  34 + /**
  35 + * 交换机名称
  36 + */
  37 + private String exchange;
  38 + /**
  39 + * 路由键
  40 + */
  41 + private String routingKey;
  42 + /**
  43 + * 队列名称
  44 + */
  45 + private String queue;
  46 +}
0 \ No newline at end of file 47 \ No newline at end of file
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/rule/vo/databridge/config/IotDataBridgeRedisStreamMQConfig.java 0 → 100644
  1 +package cn.iocoder.yudao.module.iot.controller.admin.rule.vo.databridge.config;
  2 +
  3 +import lombok.Data;
  4 +
  5 +/**
  6 + * Redis Stream MQ 配置
  7 + *
  8 + * @author HUIHUI
  9 + */
  10 +@Data
  11 +public class IotDataBridgeRedisStreamMQConfig extends IotDataBridgeConfig {
  12 +
  13 + /**
  14 + * Redis 服务器地址
  15 + */
  16 + private String host;
  17 + /**
  18 + * 端口
  19 + */
  20 + private Integer port;
  21 + /**
  22 + * 密码
  23 + */
  24 + private String password;
  25 + /**
  26 + * 数据库索引
  27 + */
  28 + private Integer database;
  29 +
  30 + /**
  31 + * 主题
  32 + */
  33 + private String topic;
  34 +}
0 \ No newline at end of file 35 \ No newline at end of file
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/rule/vo/databridge/config/IotDataBridgeRocketMQConfig.java 0 → 100644
  1 +package cn.iocoder.yudao.module.iot.controller.admin.rule.vo.databridge.config;
  2 +
  3 +import lombok.Data;
  4 +
  5 +/**
  6 + * RocketMQ 配置
  7 + *
  8 + * @author HUIHUI
  9 + */
  10 +@Data
  11 +public class IotDataBridgeRocketMQConfig extends IotDataBridgeConfig {
  12 +
  13 + /**
  14 + * RocketMQ 名称服务器地址
  15 + */
  16 + private String nameServer;
  17 + /**
  18 + * 访问密钥
  19 + */
  20 + private String accessKey;
  21 + /**
  22 + * 秘密钥匙
  23 + */
  24 + private String secretKey;
  25 +
  26 + /**
  27 + * 生产者组
  28 + */
  29 + private String group;
  30 + /**
  31 + * 主题
  32 + */
  33 + private String topic;
  34 + /**
  35 + * 标签
  36 + */
  37 + private String tags;
  38 +
  39 +}
0 \ No newline at end of file 40 \ No newline at end of file
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/rule/vo/package-info.java 0 → 100644
  1 +package cn.iocoder.yudao.module.iot.controller.admin.rule.vo;
0 \ No newline at end of file 2 \ No newline at end of file
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/rule/IotDataBridgeDO.java
1 package cn.iocoder.yudao.module.iot.dal.dataobject.rule; 1 package cn.iocoder.yudao.module.iot.dal.dataobject.rule;
2 2
3 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; 3 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
  4 +import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.databridge.config.IotDataBridgeConfig;
  5 +import cn.iocoder.yudao.module.iot.enums.rule.IotDataBridgeDirectionEnum;
  6 +import cn.iocoder.yudao.module.iot.enums.rule.IotDataBridgeTypeEnum;
4 import com.baomidou.mybatisplus.annotation.KeySequence; 7 import com.baomidou.mybatisplus.annotation.KeySequence;
5 import com.baomidou.mybatisplus.annotation.TableField; 8 import com.baomidou.mybatisplus.annotation.TableField;
6 import com.baomidou.mybatisplus.annotation.TableId; 9 import com.baomidou.mybatisplus.annotation.TableId;
7 import com.baomidou.mybatisplus.annotation.TableName; 10 import com.baomidou.mybatisplus.annotation.TableName;
8 import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler; 11 import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
9 -import com.fasterxml.jackson.annotation.JsonTypeInfo;  
10 import lombok.*; 12 import lombok.*;
11 13
12 -import java.util.Map;  
13 -  
14 /** 14 /**
15 * IoT 数据桥梁 DO 15 * IoT 数据桥梁 DO
16 * 16 *
17 * @author 芋道源码 17 * @author 芋道源码
18 */ 18 */
19 -@TableName("iot_data_bridge") 19 +@TableName(value = "iot_data_bridge", autoResultMap = true)
20 @KeySequence("iot_data_bridge_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 20 @KeySequence("iot_data_bridge_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
21 @Data 21 @Data
22 @EqualsAndHashCode(callSuper = true) 22 @EqualsAndHashCode(callSuper = true)
@@ -48,14 +48,14 @@ public class IotDataBridgeDO extends BaseDO { @@ -48,14 +48,14 @@ public class IotDataBridgeDO extends BaseDO {
48 /** 48 /**
49 * 桥梁方向 49 * 桥梁方向
50 * 50 *
51 - * 枚举 {@link cn.iocoder.yudao.module.iot.enums.rule.IotDataBridgDirectionEnum} 51 + * 枚举 {@link IotDataBridgeDirectionEnum}
52 */ 52 */
53 private Integer direction; 53 private Integer direction;
54 54
55 /** 55 /**
56 * 桥梁类型 56 * 桥梁类型
57 * 57 *
58 - * 枚举 {@link cn.iocoder.yudao.module.iot.enums.rule.IotDataBridgTypeEnum} 58 + * 枚举 {@link IotDataBridgeTypeEnum}
59 */ 59 */
60 private Integer type; 60 private Integer type;
61 61
@@ -63,211 +63,6 @@ public class IotDataBridgeDO extends BaseDO { @@ -63,211 +63,6 @@ public class IotDataBridgeDO extends BaseDO {
63 * 桥梁配置 63 * 桥梁配置
64 */ 64 */
65 @TableField(typeHandler = JacksonTypeHandler.class) 65 @TableField(typeHandler = JacksonTypeHandler.class)
66 - private Config config;  
67 -  
68 - /**  
69 - * 文件客户端的配置  
70 - * 不同实现的客户端,需要不同的配置,通过子类来定义  
71 - *  
72 - * @author 芋道源码  
73 - */  
74 - @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS)  
75 - // @JsonTypeInfo 注解的作用,Jackson 多态  
76 - // 1. 序列化到时数据库时,增加 @class 属性。  
77 - // 2. 反序列化到内存对象时,通过 @class 属性,可以创建出正确的类型  
78 - public interface Config {  
79 - }  
80 -  
81 - /**  
82 - * HTTP 配置  
83 - */  
84 - @Data  
85 - public static class HttpConfig implements Config {  
86 -  
87 - /**  
88 - * 请求 URL  
89 - */  
90 - private String url;  
91 - /**  
92 - * 请求方法  
93 - */  
94 - private String method;  
95 - /**  
96 - * 请求头  
97 - */  
98 - private Map<String, String> headers;  
99 - /**  
100 - * 请求参数  
101 - */  
102 - private Map<String, String> query;  
103 - /**  
104 - * 请求体  
105 - */  
106 - private String body;  
107 -  
108 - }  
109 -  
110 - /**  
111 - * MQTT 配置  
112 - */  
113 - @Data  
114 - public static class MqttConfig implements Config {  
115 -  
116 - /**  
117 - * MQTT 服务器地址  
118 - */  
119 - private String url;  
120 - /**  
121 - * 用户名  
122 - */  
123 - private String username;  
124 - /**  
125 - * 密码  
126 - */  
127 - private String password;  
128 - /**  
129 - * 客户端编号  
130 - */  
131 - private String clientId;  
132 - /**  
133 - * 主题  
134 - */  
135 - private String topic;  
136 -  
137 - }  
138 -  
139 - /**  
140 - * RocketMQ 配置  
141 - */  
142 - @Data  
143 - public static class RocketMQConfig implements Config {  
144 -  
145 - /**  
146 - * RocketMQ 名称服务器地址  
147 - */  
148 - private String nameServer;  
149 - /**  
150 - * 访问密钥  
151 - */  
152 - private String accessKey;  
153 - /**  
154 - * 秘密钥匙  
155 - */  
156 - private String secretKey;  
157 -  
158 - /**  
159 - * 生产者组  
160 - */  
161 - private String group;  
162 - /**  
163 - * 主题  
164 - */  
165 - private String topic;  
166 - /**  
167 - * 标签  
168 - */  
169 - private String tags;  
170 -  
171 - }  
172 -  
173 - /**  
174 - * Kafka 配置  
175 - */  
176 - @Data  
177 - public static class KafkaMQConfig implements Config {  
178 -  
179 - /**  
180 - * Kafka 服务器地址  
181 - */  
182 - private String bootstrapServers;  
183 - /**  
184 - * 用户名  
185 - */  
186 - private String username;  
187 - /**  
188 - * 密码  
189 - */  
190 - private String password;  
191 - /**  
192 - * 是否启用 SSL  
193 - */  
194 - private Boolean ssl;  
195 -  
196 - /**  
197 - * 主题  
198 - */  
199 - private String topic;  
200 -  
201 - }  
202 -  
203 - /**  
204 - * RabbitMQ 配置  
205 - */  
206 - @Data  
207 - public static class RabbitMQConfig implements Config {  
208 -  
209 - /**  
210 - * RabbitMQ 服务器地址  
211 - */  
212 - private String host;  
213 - /**  
214 - * 端口  
215 - */  
216 - private Integer port;  
217 - /**  
218 - * 虚拟主机  
219 - */  
220 - private String virtualHost;  
221 - /**  
222 - * 用户名  
223 - */  
224 - private String username;  
225 - /**  
226 - * 密码  
227 - */  
228 - private String password;  
229 -  
230 - /**  
231 - * 交换机名称  
232 - */  
233 - private String exchange;  
234 - /**  
235 - * 路由键  
236 - */  
237 - private String routingKey;  
238 - /**  
239 - * 队列名称  
240 - */  
241 - private String queue;  
242 - }  
243 -  
244 - /**  
245 - * Redis Stream MQ 配置  
246 - */  
247 - @Data  
248 - public static class RedisStreamMQConfig implements Config {  
249 -  
250 - /**  
251 - * Redis 服务器地址  
252 - */  
253 - private String host;  
254 - /**  
255 - * 端口  
256 - */  
257 - private Integer port;  
258 - /**  
259 - * 密码  
260 - */  
261 - private String password;  
262 - /**  
263 - * 数据库索引  
264 - */  
265 - private Integer database;  
266 -  
267 - /**  
268 - * 主题  
269 - */  
270 - private String topic;  
271 - } 66 + private IotDataBridgeConfig config;
272 67
273 } 68 }
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/rule/IotDataBridgeMapper.java
1 package cn.iocoder.yudao.module.iot.dal.mysql.rule; 1 package cn.iocoder.yudao.module.iot.dal.mysql.rule;
2 2
  3 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
3 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; 4 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
  5 +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
  6 +import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.databridge.IotDataBridgePageReqVO;
4 import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotDataBridgeDO; 7 import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotDataBridgeDO;
5 import org.apache.ibatis.annotations.Mapper; 8 import org.apache.ibatis.annotations.Mapper;
6 9
  10 +/**
  11 + * IoT 数据桥梁 Mapper
  12 + *
  13 + * @author HUIHUI
  14 + */
7 @Mapper 15 @Mapper
8 public interface IotDataBridgeMapper extends BaseMapperX<IotDataBridgeDO> { 16 public interface IotDataBridgeMapper extends BaseMapperX<IotDataBridgeDO> {
9 -} 17 +
  18 + default PageResult<IotDataBridgeDO> selectPage(IotDataBridgePageReqVO reqVO) {
  19 + return selectPage(reqVO, new LambdaQueryWrapperX<IotDataBridgeDO>()
  20 + .likeIfPresent(IotDataBridgeDO::getName, reqVO.getName())
  21 + .likeIfPresent(IotDataBridgeDO::getDescription, reqVO.getDescription())
  22 + .eqIfPresent(IotDataBridgeDO::getStatus, reqVO.getStatus())
  23 + .eqIfPresent(IotDataBridgeDO::getDirection, reqVO.getDirection())
  24 + .eqIfPresent(IotDataBridgeDO::getType, reqVO.getType())
  25 + .betweenIfPresent(IotDataBridgeDO::getCreateTime, reqVO.getCreateTime())
  26 + .orderByDesc(IotDataBridgeDO::getId));
  27 + }
  28 +
  29 +}
10 \ No newline at end of file 30 \ No newline at end of file
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/IotDataBridgeService.java
1 package cn.iocoder.yudao.module.iot.service.rule; 1 package cn.iocoder.yudao.module.iot.service.rule;
2 2
  3 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  4 +import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.databridge.IotDataBridgePageReqVO;
  5 +import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.databridge.IotDataBridgeSaveReqVO;
3 import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotDataBridgeDO; 6 import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotDataBridgeDO;
  7 +import jakarta.validation.Valid;
4 8
5 /** 9 /**
6 - * IoT 数据桥梁的 Service 接口 10 + * IoT 数据桥梁 Service 接口
7 * 11 *
8 - * @author 芋道源码 12 + * @author HUIHUI
9 */ 13 */
10 public interface IotDataBridgeService { 14 public interface IotDataBridgeService {
11 15
12 /** 16 /**
13 - * 获得指定数据桥梁 17 + * 创建IoT 数据桥梁
14 * 18 *
15 - * @param id 数据桥梁编号  
16 - * @return 数据桥梁 19 + * @param createReqVO 创建信息
  20 + * @return 编号
17 */ 21 */
18 - IotDataBridgeDO getIotDataBridge(Long id); 22 + Long createDataBridge(@Valid IotDataBridgeSaveReqVO createReqVO);
19 23
20 -} 24 + /**
  25 + * 更新IoT 数据桥梁
  26 + *
  27 + * @param updateReqVO 更新信息
  28 + */
  29 + void updateDataBridge(@Valid IotDataBridgeSaveReqVO updateReqVO);
  30 +
  31 + /**
  32 + * 删除IoT 数据桥梁
  33 + *
  34 + * @param id 编号
  35 + */
  36 + void deleteDataBridge(Long id);
  37 +
  38 + /**
  39 + * 获得IoT 数据桥梁
  40 + *
  41 + * @param id 编号
  42 + * @return IoT 数据桥梁
  43 + */
  44 + IotDataBridgeDO getDataBridge(Long id);
  45 +
  46 + /**
  47 + * 获得IoT 数据桥梁分页
  48 + *
  49 + * @param pageReqVO 分页查询
  50 + * @return IoT 数据桥梁分页
  51 + */
  52 + PageResult<IotDataBridgeDO> getDataBridgePage(IotDataBridgePageReqVO pageReqVO);
  53 +
  54 +}
21 \ No newline at end of file 55 \ No newline at end of file
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/IotDataBridgeServiceImpl.java
1 package cn.iocoder.yudao.module.iot.service.rule; 1 package cn.iocoder.yudao.module.iot.service.rule;
2 2
3 -import cn.hutool.core.map.MapUtil;  
4 -import cn.iocoder.yudao.framework.common.util.json.JsonUtils; 3 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  4 +import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
  5 +import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.databridge.IotDataBridgePageReqVO;
  6 +import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.databridge.IotDataBridgeSaveReqVO;
5 import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotDataBridgeDO; 7 import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotDataBridgeDO;
6 import cn.iocoder.yudao.module.iot.dal.mysql.rule.IotDataBridgeMapper; 8 import cn.iocoder.yudao.module.iot.dal.mysql.rule.IotDataBridgeMapper;
7 -import cn.iocoder.yudao.module.iot.enums.rule.IotDataBridgTypeEnum;  
8 import jakarta.annotation.Resource; 9 import jakarta.annotation.Resource;
9 -import lombok.extern.slf4j.Slf4j;  
10 import org.springframework.stereotype.Service; 10 import org.springframework.stereotype.Service;
11 import org.springframework.validation.annotation.Validated; 11 import org.springframework.validation.annotation.Validated;
12 12
13 -import java.util.Objects; 13 +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
  14 +import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.DATA_BRIDGE_NOT_EXISTS;
14 15
15 /** 16 /**
16 - * IoT 数据桥梁的 Service 实现类 17 + * IoT 数据桥梁 Service 实现类
17 * 18 *
18 - * @author 芋道源码 19 + * @author HUIHUI
19 */ 20 */
20 @Service 21 @Service
21 @Validated 22 @Validated
22 -@Slf4j  
23 public class IotDataBridgeServiceImpl implements IotDataBridgeService { 23 public class IotDataBridgeServiceImpl implements IotDataBridgeService {
24 24
25 @Resource 25 @Resource
26 private IotDataBridgeMapper dataBridgeMapper; 26 private IotDataBridgeMapper dataBridgeMapper;
27 27
28 - // TODO @芋艿:临时测试  
29 @Override 28 @Override
30 - public IotDataBridgeDO getIotDataBridge(Long id) {  
31 - if (Objects.equals(id, 1L)) {  
32 - IotDataBridgeDO.HttpConfig config = new IotDataBridgeDO.HttpConfig()  
33 - .setUrl("http://127.0.0.1:48080/test")  
34 -// .setMethod("POST")  
35 - .setMethod("GET")  
36 - .setQuery(MapUtil.of("aaa", "bbb"))  
37 - .setHeaders(MapUtil.of("ccc", "ddd"))  
38 - .setBody(JsonUtils.toJsonString(MapUtil.of("eee", "fff")));  
39 - return IotDataBridgeDO.builder().id(1L).name("芋道").description("芋道源码").status(0).direction(1)  
40 - .type(IotDataBridgTypeEnum.HTTP.getType()).config(config).build(); 29 + public Long createDataBridge(IotDataBridgeSaveReqVO createReqVO) {
  30 + // 插入
  31 + IotDataBridgeDO dataBridge = BeanUtils.toBean(createReqVO, IotDataBridgeDO.class);
  32 + dataBridgeMapper.insert(dataBridge);
  33 + // 返回
  34 + return dataBridge.getId();
  35 + }
  36 +
  37 + @Override
  38 + public void updateDataBridge(IotDataBridgeSaveReqVO updateReqVO) {
  39 + // 校验存在
  40 + validateDataBridgeExists(updateReqVO.getId());
  41 + // 更新
  42 + IotDataBridgeDO updateObj = BeanUtils.toBean(updateReqVO, IotDataBridgeDO.class);
  43 + dataBridgeMapper.updateById(updateObj);
  44 + }
  45 +
  46 + @Override
  47 + public void deleteDataBridge(Long id) {
  48 + // 校验存在
  49 + validateDataBridgeExists(id);
  50 + // 删除
  51 + dataBridgeMapper.deleteById(id);
  52 + }
  53 +
  54 + private void validateDataBridgeExists(Long id) {
  55 + if (dataBridgeMapper.selectById(id) == null) {
  56 + throw exception(DATA_BRIDGE_NOT_EXISTS);
41 } 57 }
  58 + }
  59 +
  60 + @Override
  61 + public IotDataBridgeDO getDataBridge(Long id) {
42 return dataBridgeMapper.selectById(id); 62 return dataBridgeMapper.selectById(id);
43 } 63 }
44 64
45 -} 65 + @Override
  66 + public PageResult<IotDataBridgeDO> getDataBridgePage(IotDataBridgePageReqVO pageReqVO) {
  67 + return dataBridgeMapper.selectPage(pageReqVO);
  68 + }
  69 +
  70 +}
46 \ No newline at end of file 71 \ No newline at end of file
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/action/IotRuleSceneAction.java
@@ -22,7 +22,7 @@ public interface IotRuleSceneAction { @@ -22,7 +22,7 @@ public interface IotRuleSceneAction {
22 * 2. 非空的情况:设备触发 22 * 2. 非空的情况:设备触发
23 * @param config 配置 23 * @param config 配置
24 */ 24 */
25 - void execute(@Nullable IotDeviceMessage message, IotRuleSceneDO.ActionConfig config); 25 + void execute(@Nullable IotDeviceMessage message, IotRuleSceneDO.ActionConfig config) throws Exception;
26 26
27 /** 27 /**
28 * 获得类型 28 * 获得类型
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/action/IotRuleSceneDataBridgeAction.java
@@ -26,17 +26,17 @@ public class IotRuleSceneDataBridgeAction implements IotRuleSceneAction { @@ -26,17 +26,17 @@ public class IotRuleSceneDataBridgeAction implements IotRuleSceneAction {
26 @Resource 26 @Resource
27 private IotDataBridgeService dataBridgeService; 27 private IotDataBridgeService dataBridgeService;
28 @Resource 28 @Resource
29 - private List<IotDataBridgeExecute> dataBridgeExecutes; 29 + private List<IotDataBridgeExecute<?>> dataBridgeExecutes;
30 30
31 @Override 31 @Override
32 - public void execute(IotDeviceMessage message, IotRuleSceneDO.ActionConfig config) { 32 + public void execute(IotDeviceMessage message, IotRuleSceneDO.ActionConfig config) throws Exception {
33 // 1.1 如果消息为空,直接返回 33 // 1.1 如果消息为空,直接返回
34 if (message == null) { 34 if (message == null) {
35 return; 35 return;
36 } 36 }
37 // 1.2 获得数据桥梁 37 // 1.2 获得数据桥梁
38 Assert.notNull(config.getDataBridgeId(), "数据桥梁编号不能为空"); 38 Assert.notNull(config.getDataBridgeId(), "数据桥梁编号不能为空");
39 - IotDataBridgeDO dataBridge = dataBridgeService.getIotDataBridge(config.getDataBridgeId()); 39 + IotDataBridgeDO dataBridge = dataBridgeService.getDataBridge(config.getDataBridgeId());
40 if (dataBridge == null || dataBridge.getConfig() == null) { 40 if (dataBridge == null || dataBridge.getConfig() == null) {
41 log.error("[execute][message({}) config({}) 对应的数据桥梁不存在]", message, config); 41 log.error("[execute][message({}) config({}) 对应的数据桥梁不存在]", message, config);
42 return; 42 return;
@@ -47,7 +47,9 @@ public class IotRuleSceneDataBridgeAction implements IotRuleSceneAction { @@ -47,7 +47,9 @@ public class IotRuleSceneDataBridgeAction implements IotRuleSceneAction {
47 } 47 }
48 48
49 // 2. 执行数据桥接操作 49 // 2. 执行数据桥接操作
50 - dataBridgeExecutes.forEach(execute -> execute.execute(message, dataBridge)); 50 + for (IotDataBridgeExecute<?> execute : dataBridgeExecutes) {
  51 + execute.execute(message, dataBridge);
  52 + }
51 } 53 }
52 54
53 @Override 55 @Override
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/action/databridge/AbstractCacheableDataBridgeExecute.java
1 package cn.iocoder.yudao.module.iot.service.rule.action.databridge; 1 package cn.iocoder.yudao.module.iot.service.rule.action.databridge;
2 2
  3 +import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotDataBridgeDO;
  4 +import cn.iocoder.yudao.module.iot.mq.message.IotDeviceMessage;
3 import com.google.common.cache.CacheBuilder; 5 import com.google.common.cache.CacheBuilder;
4 import com.google.common.cache.CacheLoader; 6 import com.google.common.cache.CacheLoader;
5 import com.google.common.cache.LoadingCache; 7 import com.google.common.cache.LoadingCache;
  8 +import com.google.common.cache.RemovalListener;
6 import lombok.extern.slf4j.Slf4j; 9 import lombok.extern.slf4j.Slf4j;
7 10
8 import java.time.Duration; 11 import java.time.Duration;
@@ -15,22 +18,36 @@ import java.time.Duration; @@ -15,22 +18,36 @@ import java.time.Duration;
15 /** 18 /**
16 * 带缓存功能的数据桥梁执行器抽象类 19 * 带缓存功能的数据桥梁执行器抽象类
17 * 20 *
  21 + * 该类提供了一个通用的缓存机制,用于管理各类数据桥接的生产者(Producer)实例。
  22 + *
  23 + * 主要特点:
  24 + * - 基于Guava Cache实现高效的生产者实例缓存管理
  25 + * - 自动处理生产者的生命周期(创建、获取、关闭)
  26 + * - 支持30分钟未访问自动过期清理机制
  27 + * - 异常处理与日志记录,便于问题排查
  28 + *
  29 + * 子类需要实现:
  30 + * - initProducer(Config) - 初始化特定类型的生产者实例
  31 + * - closeProducer(Producer) - 关闭生产者实例并释放资源
  32 + *
  33 + * @param <Config> 配置信息类型,用于初始化生产者
  34 + * @param <Producer> 生产者类型,负责将数据发送到目标系统
18 * @author HUIHUI 35 * @author HUIHUI
19 */ 36 */
20 @Slf4j 37 @Slf4j
21 -public abstract class AbstractCacheableDataBridgeExecute implements IotDataBridgeExecute { 38 +public abstract class AbstractCacheableDataBridgeExecute<Config, Producer> implements IotDataBridgeExecute<Config> {
22 39
23 - // TODO @huihui:AbstractCacheableDataBridgeExecute<Producer> 这样,下面的 Object, Object 就有了类型;另外 IotDataBridgeDO.Config 可以替代一个 Object 哇,  
24 /** 40 /**
25 * Producer 缓存 41 * Producer 缓存
26 */ 42 */
27 - private final LoadingCache<Object, Object> PRODUCER_CACHE = CacheBuilder.newBuilder()  
28 - .expireAfterAccess(Duration.ofMinutes(30))  
29 - .removalListener(notification -> {  
30 - Object producer = notification.getValue(); 43 + private final LoadingCache<Config, Producer> PRODUCER_CACHE = CacheBuilder.newBuilder()
  44 + .expireAfterAccess(Duration.ofMinutes(30)) // 30 分钟未访问就提前过期
  45 + .removalListener((RemovalListener<Config, Producer>) notification -> {
  46 + Producer producer = notification.getValue();
31 if (producer == null) { 47 if (producer == null) {
32 return; 48 return;
33 } 49 }
  50 +
34 try { 51 try {
35 closeProducer(producer); 52 closeProducer(producer);
36 log.info("[PRODUCER_CACHE][配置({}) 对应的 producer 已关闭]", notification.getKey()); 53 log.info("[PRODUCER_CACHE][配置({}) 对应的 producer 已关闭]", notification.getKey());
@@ -38,15 +55,18 @@ public abstract class AbstractCacheableDataBridgeExecute implements IotDataBridg @@ -38,15 +55,18 @@ public abstract class AbstractCacheableDataBridgeExecute implements IotDataBridg
38 log.error("[PRODUCER_CACHE][配置({}) 对应的 producer 关闭失败]", notification.getKey(), e); 55 log.error("[PRODUCER_CACHE][配置({}) 对应的 producer 关闭失败]", notification.getKey(), e);
39 } 56 }
40 }) 57 })
41 - .build(new CacheLoader<Object, Object>() {  
42 - 58 + .build(new CacheLoader<Config, Producer>() {
43 @Override 59 @Override
44 - public Object load(Object config) throws Exception {  
45 - Object producer = initProducer(config);  
46 - log.info("[PRODUCER_CACHE][配置({}) 对应的 producer 已创建并启动]", config);  
47 - return producer; 60 + public Producer load(Config config) throws Exception {
  61 + try {
  62 + Producer producer = initProducer(config);
  63 + log.info("[PRODUCER_CACHE][配置({}) 对应的 producer 已创建并启动]", config);
  64 + return producer;
  65 + } catch (Exception e) {
  66 + log.error("[PRODUCER_CACHE][配置({}) 对应的 producer 创建启动失败]", config, e);
  67 + throw e; // 抛出异常,触发缓存加载失败机制
  68 + }
48 } 69 }
49 -  
50 }); 70 });
51 71
52 /** 72 /**
@@ -55,7 +75,7 @@ public abstract class AbstractCacheableDataBridgeExecute implements IotDataBridg @@ -55,7 +75,7 @@ public abstract class AbstractCacheableDataBridgeExecute implements IotDataBridg
55 * @param config 配置信息 75 * @param config 配置信息
56 * @return 生产者对象 76 * @return 生产者对象
57 */ 77 */
58 - protected Object getProducer(Object config) throws Exception { 78 + protected Producer getProducer(Config config) throws Exception {
59 return PRODUCER_CACHE.get(config); 79 return PRODUCER_CACHE.get(config);
60 } 80 }
61 81
@@ -66,13 +86,29 @@ public abstract class AbstractCacheableDataBridgeExecute implements IotDataBridg @@ -66,13 +86,29 @@ public abstract class AbstractCacheableDataBridgeExecute implements IotDataBridg
66 * @return 生产者对象 86 * @return 生产者对象
67 * @throws Exception 如果初始化失败 87 * @throws Exception 如果初始化失败
68 */ 88 */
69 - protected abstract Object initProducer(Object config) throws Exception; 89 + protected abstract Producer initProducer(Config config) throws Exception;
70 90
71 /** 91 /**
72 * 关闭生产者 92 * 关闭生产者
73 * 93 *
74 * @param producer 生产者对象 94 * @param producer 生产者对象
75 */ 95 */
76 - protected abstract void closeProducer(Object producer); 96 + protected abstract void closeProducer(Producer producer) throws Exception;
  97 +
  98 + @Override
  99 + @SuppressWarnings({"unchecked"})
  100 + public void execute(IotDeviceMessage message, IotDataBridgeDO dataBridge) {
  101 + // 1.1 校验数据桥梁类型
  102 + if (!getType().equals(dataBridge.getType())) {
  103 + return;
  104 + }
  105 +
  106 + // 1.2 执行对应的数据桥梁发送消息
  107 + try {
  108 + execute0(message, (Config) dataBridge.getConfig());
  109 + } catch (Exception e) {
  110 + log.error("[execute][桥梁配置 config({}) 对应的 message({}) 发送异常]", dataBridge.getConfig(), message, e);
  111 + }
  112 + }
77 113
78 } 114 }
79 \ No newline at end of file 115 \ 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
@@ -9,9 +9,14 @@ import cn.iocoder.yudao.module.iot.mq.message.IotDeviceMessage; @@ -9,9 +9,14 @@ import cn.iocoder.yudao.module.iot.mq.message.IotDeviceMessage;
9 * 9 *
10 * @author HUIHUI 10 * @author HUIHUI
11 */ 11 */
12 -public interface IotDataBridgeExecute { 12 +public interface IotDataBridgeExecute<Config> {
13 13
14 - // TODO @huihui:要不搞个 getType?然后 execute0 由子类实现。这样,子类的 executeRedisStream ,其实就是 execute0 了。 14 + /**
  15 + * 获取数据桥梁类型
  16 + *
  17 + * @return 数据桥梁类型
  18 + */
  19 + Integer getType();
15 20
16 /** 21 /**
17 * 执行数据桥梁操作 22 * 执行数据桥梁操作
@@ -19,6 +24,23 @@ public interface IotDataBridgeExecute { @@ -19,6 +24,23 @@ public interface IotDataBridgeExecute {
19 * @param message 设备消息 24 * @param message 设备消息
20 * @param dataBridge 数据桥梁 25 * @param dataBridge 数据桥梁
21 */ 26 */
22 - void execute(IotDeviceMessage message, IotDataBridgeDO dataBridge); 27 + @SuppressWarnings({"unchecked"})
  28 + default void execute(IotDeviceMessage message, IotDataBridgeDO dataBridge) throws Exception {
  29 + // 1.1 校验数据桥梁类型
  30 + if (!getType().equals(dataBridge.getType())) {
  31 + return;
  32 + }
  33 +
  34 + // 1.2 执行对应的数据桥梁发送消息
  35 + execute0(message, (Config) dataBridge.getConfig());
  36 + }
  37 +
  38 + /**
  39 + * 【真正】执行数据桥梁操作
  40 + *
  41 + * @param message 设备消息
  42 + * @param config 桥梁配置
  43 + */
  44 + void execute0(IotDeviceMessage message, Config config) throws Exception;
23 45
24 } 46 }
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/action/databridge/IotHttpDataBridgeExecute.java
@@ -3,8 +3,8 @@ package cn.iocoder.yudao.module.iot.service.rule.action.databridge; @@ -3,8 +3,8 @@ package cn.iocoder.yudao.module.iot.service.rule.action.databridge;
3 import cn.hutool.core.collection.CollUtil; 3 import cn.hutool.core.collection.CollUtil;
4 import cn.iocoder.yudao.framework.common.util.http.HttpUtils; 4 import cn.iocoder.yudao.framework.common.util.http.HttpUtils;
5 import cn.iocoder.yudao.framework.common.util.json.JsonUtils; 5 import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
6 -import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotDataBridgeDO;  
7 -import cn.iocoder.yudao.module.iot.enums.rule.IotDataBridgTypeEnum; 6 +import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.databridge.config.IotDataBridgeHttpConfig;
  7 +import cn.iocoder.yudao.module.iot.enums.rule.IotDataBridgeTypeEnum;
8 import cn.iocoder.yudao.module.iot.mq.message.IotDeviceMessage; 8 import cn.iocoder.yudao.module.iot.mq.message.IotDeviceMessage;
9 import jakarta.annotation.Resource; 9 import jakarta.annotation.Resource;
10 import lombok.extern.slf4j.Slf4j; 10 import lombok.extern.slf4j.Slf4j;
@@ -25,23 +25,19 @@ import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.HEADER_ @@ -25,23 +25,19 @@ import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.HEADER_
25 */ 25 */
26 @Component 26 @Component
27 @Slf4j 27 @Slf4j
28 -public class IotHttpDataBridgeExecute implements IotDataBridgeExecute { 28 +public class IotHttpDataBridgeExecute implements IotDataBridgeExecute<IotDataBridgeHttpConfig> {
29 29
30 @Resource 30 @Resource
31 private RestTemplate restTemplate; 31 private RestTemplate restTemplate;
32 32
33 @Override 33 @Override
34 - public void execute(IotDeviceMessage message, IotDataBridgeDO dataBridge) {  
35 - // 1.1 校验数据桥梁的类型 == HTTP  
36 - if (!IotDataBridgTypeEnum.HTTP.getType().equals(dataBridge.getType())) {  
37 - return;  
38 - }  
39 - // 1.2 执行 HTTP 请求  
40 - executeHttp(message, (IotDataBridgeDO.HttpConfig) dataBridge.getConfig()); 34 + public Integer getType() {
  35 + return IotDataBridgeTypeEnum.HTTP.getType();
41 } 36 }
42 37
  38 + @Override
43 @SuppressWarnings({"unchecked", "deprecation"}) 39 @SuppressWarnings({"unchecked", "deprecation"})
44 - private void executeHttp(IotDeviceMessage message, IotDataBridgeDO.HttpConfig config) { 40 + public void execute0(IotDeviceMessage message, IotDataBridgeHttpConfig config) {
45 String url = null; 41 String url = null;
46 HttpMethod method = HttpMethod.valueOf(config.getMethod().toUpperCase()); 42 HttpMethod method = HttpMethod.valueOf(config.getMethod().toUpperCase());
47 HttpEntity<String> requestEntity = null; 43 HttpEntity<String> requestEntity = null;
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/action/databridge/IotKafkaMQDataBridgeExecute.java
1 package cn.iocoder.yudao.module.iot.service.rule.action.databridge; 1 package cn.iocoder.yudao.module.iot.service.rule.action.databridge;
2 2
  3 +import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.databridge.config.IotDataBridgeKafkaMQConfig;
3 import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotDataBridgeDO; 4 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.enums.rule.IotDataBridgeTypeEnum;
5 import cn.iocoder.yudao.module.iot.mq.message.IotDeviceMessage; 6 import cn.iocoder.yudao.module.iot.mq.message.IotDeviceMessage;
6 import lombok.extern.slf4j.Slf4j; 7 import lombok.extern.slf4j.Slf4j;
7 import org.apache.kafka.clients.producer.ProducerConfig; 8 import org.apache.kafka.clients.producer.ProducerConfig;
8 import org.apache.kafka.common.serialization.StringSerializer; 9 import org.apache.kafka.common.serialization.StringSerializer;
  10 +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
9 import org.springframework.kafka.core.DefaultKafkaProducerFactory; 11 import org.springframework.kafka.core.DefaultKafkaProducerFactory;
10 import org.springframework.kafka.core.KafkaTemplate; 12 import org.springframework.kafka.core.KafkaTemplate;
11 import org.springframework.stereotype.Component; 13 import org.springframework.stereotype.Component;
@@ -15,65 +17,53 @@ import java.time.LocalDateTime; @@ -15,65 +17,53 @@ import java.time.LocalDateTime;
15 import java.util.HashMap; 17 import java.util.HashMap;
16 import java.util.Map; 18 import java.util.Map;
17 import java.util.concurrent.TimeUnit; 19 import java.util.concurrent.TimeUnit;
18 -import java.util.concurrent.TimeoutException;  
19 20
20 /** 21 /**
21 * Kafka 的 {@link IotDataBridgeExecute} 实现类 22 * Kafka 的 {@link IotDataBridgeExecute} 实现类
22 * 23 *
23 * @author HUIHUI 24 * @author HUIHUI
24 */ 25 */
  26 +@ConditionalOnClass(name = "org.springframework.kafka.core.KafkaTemplate")
25 @Component 27 @Component
26 @Slf4j 28 @Slf4j
27 -public class IotKafkaMQDataBridgeExecute extends AbstractCacheableDataBridgeExecute { 29 +public class IotKafkaMQDataBridgeExecute extends
  30 + AbstractCacheableDataBridgeExecute<IotDataBridgeKafkaMQConfig, KafkaTemplate<String, String>> {
28 31
29 - private static final Duration SEND_TIMEOUT = Duration.ofMillis(10); 32 + private static final Duration SEND_TIMEOUT = Duration.ofMillis(10000); // 10 秒超时时间
30 33
31 @Override 34 @Override
32 - public void execute(IotDeviceMessage message, IotDataBridgeDO dataBridge) {  
33 - // 1. 校验数据桥梁的类型 == KAFKA  
34 - if (!IotDataBridgTypeEnum.KAFKA.getType().equals(dataBridge.getType())) {  
35 - return;  
36 - }  
37 - // 2. 执行 Kafka 发送消息  
38 - executeKafka(message, (IotDataBridgeDO.KafkaMQConfig) dataBridge.getConfig()); 35 + public Integer getType() {
  36 + return IotDataBridgeTypeEnum.KAFKA.getType();
39 } 37 }
40 38
41 - @SuppressWarnings("unchecked")  
42 - private void executeKafka(IotDeviceMessage message, IotDataBridgeDO.KafkaMQConfig config) {  
43 - try {  
44 - // 1. 获取或创建 KafkaTemplate  
45 - KafkaTemplate<String, String> kafkaTemplate = (KafkaTemplate<String, String>) getProducer(config);  
46 -  
47 - // 2. 发送消息并等待结果  
48 - kafkaTemplate.send(config.getTopic(), message.toString())  
49 - .get(SEND_TIMEOUT.getSeconds(), TimeUnit.SECONDS); // 添加超时等待  
50 - log.info("[executeKafka][message({}) 发送成功]", message);  
51 - } catch (TimeoutException e) {  
52 - log.error("[executeKafka][message({}) config({}) 发送超时]", message, config, e);  
53 - } catch (Exception e) {  
54 - log.error("[executeKafka][message({}) config({}) 发送异常]", message, config, e);  
55 - } 39 + @Override
  40 + public void execute0(IotDeviceMessage message, IotDataBridgeKafkaMQConfig config) throws Exception {
  41 + // 1. 获取或创建 KafkaTemplate
  42 + KafkaTemplate<String, String> kafkaTemplate = getProducer(config);
  43 +
  44 + // 2. 发送消息并等待结果
  45 + kafkaTemplate.send(config.getTopic(), message.toString())
  46 + .get(SEND_TIMEOUT.getSeconds(), TimeUnit.SECONDS); // 添加超时等待
  47 + log.info("[execute0][message({}) 发送成功]", message);
56 } 48 }
57 49
58 @Override 50 @Override
59 - protected Object initProducer(Object config) {  
60 - IotDataBridgeDO.KafkaMQConfig kafkaConfig = (IotDataBridgeDO.KafkaMQConfig) config;  
61 - 51 + protected KafkaTemplate<String, String> initProducer(IotDataBridgeKafkaMQConfig config) {
62 // 1.1 构建生产者配置 52 // 1.1 构建生产者配置
63 Map<String, Object> props = new HashMap<>(); 53 Map<String, Object> props = new HashMap<>();
64 - props.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, kafkaConfig.getBootstrapServers()); 54 + props.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, config.getBootstrapServers());
65 props.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class); 55 props.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class);
66 props.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, StringSerializer.class); 56 props.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, StringSerializer.class);
67 // 1.2 如果配置了认证信息 57 // 1.2 如果配置了认证信息
68 - if (kafkaConfig.getUsername() != null && kafkaConfig.getPassword() != null) { 58 + if (config.getUsername() != null && config.getPassword() != null) {
69 props.put("security.protocol", "SASL_PLAINTEXT"); 59 props.put("security.protocol", "SASL_PLAINTEXT");
70 props.put("sasl.mechanism", "PLAIN"); 60 props.put("sasl.mechanism", "PLAIN");
71 props.put("sasl.jaas.config", 61 props.put("sasl.jaas.config",
72 "org.apache.kafka.common.security.plain.PlainLoginModule required username=\"" 62 "org.apache.kafka.common.security.plain.PlainLoginModule required username=\""
73 - + kafkaConfig.getUsername() + "\" password=\"" + kafkaConfig.getPassword() + "\";"); 63 + + config.getUsername() + "\" password=\"" + config.getPassword() + "\";");
74 } 64 }
75 // 1.3 如果启用 SSL 65 // 1.3 如果启用 SSL
76 - if (Boolean.TRUE.equals(kafkaConfig.getSsl())) { 66 + if (Boolean.TRUE.equals(config.getSsl())) {
77 props.put("security.protocol", "SSL"); 67 props.put("security.protocol", "SSL");
78 } 68 }
79 69
@@ -83,10 +73,8 @@ public class IotKafkaMQDataBridgeExecute extends AbstractCacheableDataBridgeExec @@ -83,10 +73,8 @@ public class IotKafkaMQDataBridgeExecute extends AbstractCacheableDataBridgeExec
83 } 73 }
84 74
85 @Override 75 @Override
86 - protected void closeProducer(Object producer) {  
87 - if (producer instanceof KafkaTemplate) {  
88 - ((KafkaTemplate<?, ?>) producer).destroy();  
89 - } 76 + protected void closeProducer(KafkaTemplate<String, String> producer) {
  77 + producer.destroy();
90 } 78 }
91 79
92 // TODO @芋艿:测试代码,后续清理 80 // TODO @芋艿:测试代码,后续清理
@@ -95,7 +83,7 @@ public class IotKafkaMQDataBridgeExecute extends AbstractCacheableDataBridgeExec @@ -95,7 +83,7 @@ public class IotKafkaMQDataBridgeExecute extends AbstractCacheableDataBridgeExec
95 IotKafkaMQDataBridgeExecute action = new IotKafkaMQDataBridgeExecute(); 83 IotKafkaMQDataBridgeExecute action = new IotKafkaMQDataBridgeExecute();
96 84
97 // 2. 创建共享的配置 85 // 2. 创建共享的配置
98 - IotDataBridgeDO.KafkaMQConfig config = new IotDataBridgeDO.KafkaMQConfig(); 86 + IotDataBridgeKafkaMQConfig config = new IotDataBridgeKafkaMQConfig();
99 config.setBootstrapServers("127.0.0.1:9092"); 87 config.setBootstrapServers("127.0.0.1:9092");
100 config.setTopic("test-topic"); 88 config.setTopic("test-topic");
101 config.setSsl(false); 89 config.setSsl(false);
@@ -117,10 +105,10 @@ public class IotKafkaMQDataBridgeExecute extends AbstractCacheableDataBridgeExec @@ -117,10 +105,10 @@ public class IotKafkaMQDataBridgeExecute extends AbstractCacheableDataBridgeExec
117 105
118 // 4. 执行两次测试,验证缓存 106 // 4. 执行两次测试,验证缓存
119 log.info("[main][第一次执行,应该会创建新的 producer]"); 107 log.info("[main][第一次执行,应该会创建新的 producer]");
120 - action.executeKafka(message, config); 108 + action.execute(message, new IotDataBridgeDO().setType(action.getType()).setConfig(config));
121 109
122 log.info("[main][第二次执行,应该会复用缓存的 producer]"); 110 log.info("[main][第二次执行,应该会复用缓存的 producer]");
123 - action.executeKafka(message, config); 111 + action.execute(message, new IotDataBridgeDO().setType(action.getType()).setConfig(config));
124 } 112 }
125 113
126 } 114 }
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/action/databridge/IotRabbitMQDataBridgeExecute.java
1 package cn.iocoder.yudao.module.iot.service.rule.action.databridge; 1 package cn.iocoder.yudao.module.iot.service.rule.action.databridge;
2 2
  3 +import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.databridge.config.IotDataBridgeRabbitMQConfig;
3 import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotDataBridgeDO; 4 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.enums.rule.IotDataBridgeTypeEnum;
5 import cn.iocoder.yudao.module.iot.mq.message.IotDeviceMessage; 6 import cn.iocoder.yudao.module.iot.mq.message.IotDeviceMessage;
6 import com.rabbitmq.client.Channel; 7 import com.rabbitmq.client.Channel;
7 import com.rabbitmq.client.Connection; 8 import com.rabbitmq.client.Connection;
8 import com.rabbitmq.client.ConnectionFactory; 9 import com.rabbitmq.client.ConnectionFactory;
9 import lombok.extern.slf4j.Slf4j; 10 import lombok.extern.slf4j.Slf4j;
  11 +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
10 import org.springframework.stereotype.Component; 12 import org.springframework.stereotype.Component;
11 13
12 import java.nio.charset.StandardCharsets; 14 import java.nio.charset.StandardCharsets;
@@ -17,51 +19,44 @@ import java.time.LocalDateTime; @@ -17,51 +19,44 @@ import java.time.LocalDateTime;
17 * 19 *
18 * @author HUIHUI 20 * @author HUIHUI
19 */ 21 */
  22 +@ConditionalOnClass(name = "com.rabbitmq.client.Channel")
20 @Component 23 @Component
21 @Slf4j 24 @Slf4j
22 -public class IotRabbitMQDataBridgeExecute extends AbstractCacheableDataBridgeExecute { 25 +public class IotRabbitMQDataBridgeExecute extends
  26 + AbstractCacheableDataBridgeExecute<IotDataBridgeRabbitMQConfig, Channel> {
  27 +
23 28
24 @Override 29 @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()); 30 + public Integer getType() {
  31 + return IotDataBridgeTypeEnum.RABBITMQ.getType();
32 } 32 }
33 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 - } 34 + @Override
  35 + public void execute0(IotDeviceMessage message, IotDataBridgeRabbitMQConfig config) throws Exception {
  36 + // 1. 获取或创建 Channel
  37 + 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);
51 } 48 }
52 49
53 @Override 50 @Override
54 @SuppressWarnings("resource") 51 @SuppressWarnings("resource")
55 - protected Object initProducer(Object config) throws Exception {  
56 - IotDataBridgeDO.RabbitMQConfig rabbitConfig = (IotDataBridgeDO.RabbitMQConfig) config;  
57 - 52 + protected Channel initProducer(IotDataBridgeRabbitMQConfig config) throws Exception {
58 // 1. 创建连接工厂 53 // 1. 创建连接工厂
59 ConnectionFactory factory = new ConnectionFactory(); 54 ConnectionFactory factory = new ConnectionFactory();
60 - factory.setHost(rabbitConfig.getHost());  
61 - factory.setPort(rabbitConfig.getPort());  
62 - factory.setVirtualHost(rabbitConfig.getVirtualHost());  
63 - factory.setUsername(rabbitConfig.getUsername());  
64 - factory.setPassword(rabbitConfig.getPassword()); 55 + factory.setHost(config.getHost());
  56 + factory.setPort(config.getPort());
  57 + factory.setVirtualHost(config.getVirtualHost());
  58 + factory.setUsername(config.getUsername());
  59 + factory.setPassword(config.getPassword());
65 60
66 // 2. 创建连接 61 // 2. 创建连接
67 Connection connection = factory.newConnection(); 62 Connection connection = factory.newConnection();
@@ -71,20 +66,13 @@ public class IotRabbitMQDataBridgeExecute extends AbstractCacheableDataBridgeExe @@ -71,20 +66,13 @@ public class IotRabbitMQDataBridgeExecute extends AbstractCacheableDataBridgeExe
71 } 66 }
72 67
73 @Override 68 @Override
74 - protected void closeProducer(Object producer) {  
75 - if (producer instanceof Channel) {  
76 - try {  
77 - Channel channel = (Channel) producer;  
78 - if (channel.isOpen()) {  
79 - channel.close();  
80 - }  
81 - Connection connection = channel.getConnection();  
82 - if (connection.isOpen()) {  
83 - connection.close();  
84 - }  
85 - } catch (Exception e) {  
86 - log.error("[closeProducer][关闭 RabbitMQ 连接异常]", e);  
87 - } 69 + protected void closeProducer(Channel channel) throws Exception {
  70 + if (channel.isOpen()) {
  71 + channel.close();
  72 + }
  73 + Connection connection = channel.getConnection();
  74 + if (connection.isOpen()) {
  75 + connection.close();
88 } 76 }
89 } 77 }
90 78
@@ -94,7 +82,7 @@ public class IotRabbitMQDataBridgeExecute extends AbstractCacheableDataBridgeExe @@ -94,7 +82,7 @@ public class IotRabbitMQDataBridgeExecute extends AbstractCacheableDataBridgeExe
94 IotRabbitMQDataBridgeExecute action = new IotRabbitMQDataBridgeExecute(); 82 IotRabbitMQDataBridgeExecute action = new IotRabbitMQDataBridgeExecute();
95 83
96 // 2. 创建共享的配置 84 // 2. 创建共享的配置
97 - IotDataBridgeDO.RabbitMQConfig config = new IotDataBridgeDO.RabbitMQConfig(); 85 + IotDataBridgeRabbitMQConfig config = new IotDataBridgeRabbitMQConfig();
98 config.setHost("localhost"); 86 config.setHost("localhost");
99 config.setPort(5672); 87 config.setPort(5672);
100 config.setVirtualHost("/"); 88 config.setVirtualHost("/");
@@ -118,10 +106,12 @@ public class IotRabbitMQDataBridgeExecute extends AbstractCacheableDataBridgeExe @@ -118,10 +106,12 @@ public class IotRabbitMQDataBridgeExecute extends AbstractCacheableDataBridgeExe
118 .build(); 106 .build();
119 107
120 // 4. 执行两次测试,验证缓存 108 // 4. 执行两次测试,验证缓存
121 - log.info("[main][第一次执行,应该会创建新的 channel]");  
122 - action.executeRabbitMQ(message, config); 109 + // 4. 执行两次测试,验证缓存
  110 + log.info("[main][第一次执行,应该会创建新的 producer]");
  111 + action.execute(message, new IotDataBridgeDO().setType(action.getType()).setConfig(config));
123 112
124 - log.info("[main][第二次执行,应该会复用缓存的 channel]");  
125 - action.executeRabbitMQ(message, config); 113 + log.info("[main][第二次执行,应该会复用缓存的 producer]");
  114 + action.execute(message, new IotDataBridgeDO().setType(action.getType()).setConfig(config));
126 } 115 }
  116 +
127 } 117 }
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/action/databridge/IotRedisStreamMQDataBridgeExecute.java
@@ -2,8 +2,9 @@ package cn.iocoder.yudao.module.iot.service.rule.action.databridge; @@ -2,8 +2,9 @@ package cn.iocoder.yudao.module.iot.service.rule.action.databridge;
2 2
3 import cn.hutool.core.util.ReflectUtil; 3 import cn.hutool.core.util.ReflectUtil;
4 import cn.hutool.core.util.StrUtil; 4 import cn.hutool.core.util.StrUtil;
  5 +import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.databridge.config.IotDataBridgeRedisStreamMQConfig;
5 import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotDataBridgeDO; 6 import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotDataBridgeDO;
6 -import cn.iocoder.yudao.module.iot.enums.rule.IotDataBridgTypeEnum; 7 +import cn.iocoder.yudao.module.iot.enums.rule.IotDataBridgeTypeEnum;
7 import cn.iocoder.yudao.module.iot.mq.message.IotDeviceMessage; 8 import cn.iocoder.yudao.module.iot.mq.message.IotDeviceMessage;
8 import com.fasterxml.jackson.databind.ObjectMapper; 9 import com.fasterxml.jackson.databind.ObjectMapper;
9 import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; 10 import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
@@ -29,47 +30,36 @@ import java.time.LocalDateTime; @@ -29,47 +30,36 @@ import java.time.LocalDateTime;
29 */ 30 */
30 @Component 31 @Component
31 @Slf4j 32 @Slf4j
32 -public class IotRedisStreamMQDataBridgeExecute extends AbstractCacheableDataBridgeExecute { 33 +public class IotRedisStreamMQDataBridgeExecute extends
  34 + AbstractCacheableDataBridgeExecute<IotDataBridgeRedisStreamMQConfig, RedisTemplate<String, Object>> {
33 35
34 @Override 36 @Override
35 - public void execute(IotDeviceMessage message, IotDataBridgeDO dataBridge) {  
36 - // 1.1 校验数据桥梁类型  
37 - if (!IotDataBridgTypeEnum.REDIS_STREAM.getType().equals(dataBridge.getType())) {  
38 - return;  
39 - }  
40 - // 1.2 执行消息发送  
41 - executeRedisStream(message, (IotDataBridgeDO.RedisStreamMQConfig) dataBridge.getConfig()); 37 + public Integer getType() {
  38 + return IotDataBridgeTypeEnum.REDIS_STREAM.getType();
42 } 39 }
43 40
44 - @SuppressWarnings("unchecked")  
45 - // TODO @huihui:try catch 交给父类来做,子类不处理异常  
46 - private void executeRedisStream(IotDeviceMessage message, IotDataBridgeDO.RedisStreamMQConfig config) {  
47 - try {  
48 - // 1. 获取 RedisTemplate  
49 - RedisTemplate<String, Object> redisTemplate = (RedisTemplate<String, Object>) getProducer(config);  
50 -  
51 - // 2. 创建并发送 Stream 记录  
52 - ObjectRecord<String, IotDeviceMessage> record = StreamRecords.newRecord()  
53 - .ofObject(message).withStreamKey(config.getTopic());  
54 - String recordId = String.valueOf(redisTemplate.opsForStream().add(record));  
55 - log.info("[executeRedisStream][消息发送成功] messageId: {}, config: {}", recordId, config);  
56 - } catch (Exception e) {  
57 - log.error("[executeRedisStream][消息发送失败] message: {}, config: {}", message, config, e);  
58 - } 41 + @Override
  42 + public void execute0(IotDeviceMessage message, IotDataBridgeRedisStreamMQConfig config) throws Exception {
  43 + // 1. 获取 RedisTemplate
  44 + RedisTemplate<String, Object> redisTemplate = getProducer(config);
  45 +
  46 + // 2. 创建并发送 Stream 记录
  47 + ObjectRecord<String, IotDeviceMessage> record = StreamRecords.newRecord()
  48 + .ofObject(message).withStreamKey(config.getTopic());
  49 + String recordId = String.valueOf(redisTemplate.opsForStream().add(record));
  50 + log.info("[executeRedisStream][消息发送成功] messageId: {}, config: {}", recordId, config);
59 } 51 }
60 52
61 @Override 53 @Override
62 - protected Object initProducer(Object config) {  
63 - IotDataBridgeDO.RedisStreamMQConfig redisConfig = (IotDataBridgeDO.RedisStreamMQConfig) config;  
64 - 54 + protected RedisTemplate<String, Object> initProducer(IotDataBridgeRedisStreamMQConfig config) {
65 // 1.1 创建 Redisson 配置 55 // 1.1 创建 Redisson 配置
66 Config redissonConfig = new Config(); 56 Config redissonConfig = new Config();
67 SingleServerConfig serverConfig = redissonConfig.useSingleServer() 57 SingleServerConfig serverConfig = redissonConfig.useSingleServer()
68 - .setAddress("redis://" + redisConfig.getHost() + ":" + redisConfig.getPort())  
69 - .setDatabase(redisConfig.getDatabase()); 58 + .setAddress("redis://" + config.getHost() + ":" + config.getPort())
  59 + .setDatabase(config.getDatabase());
70 // 1.2 设置密码(如果有) 60 // 1.2 设置密码(如果有)
71 - if (StrUtil.isNotBlank(redisConfig.getPassword())) {  
72 - serverConfig.setPassword(redisConfig.getPassword()); 61 + if (StrUtil.isNotBlank(config.getPassword())) {
  62 + serverConfig.setPassword(config.getPassword());
73 } 63 }
74 64
75 // TODO @huihui:看看能不能简化一些。按道理说,不用这么多的哈。 65 // TODO @huihui:看看能不能简化一些。按道理说,不用这么多的哈。
@@ -90,17 +80,10 @@ public class IotRedisStreamMQDataBridgeExecute extends AbstractCacheableDataBrid @@ -90,17 +80,10 @@ public class IotRedisStreamMQDataBridgeExecute extends AbstractCacheableDataBrid
90 } 80 }
91 81
92 @Override 82 @Override
93 - protected void closeProducer(Object producer) {  
94 - // TODO @huihui:try catch 交给父类来做。子类不处理异常  
95 - if (producer instanceof RedisTemplate) {  
96 - RedisConnectionFactory factory = ((RedisTemplate<?, ?>) producer).getConnectionFactory();  
97 - try {  
98 - if (factory != null) {  
99 - ((RedissonConnectionFactory) factory).destroy();  
100 - }  
101 - } catch (Exception e) {  
102 - log.error("[closeProducer][关闭 redisson 连接异常]", e);  
103 - } 83 + protected void closeProducer(RedisTemplate<String, Object> producer) throws Exception {
  84 + RedisConnectionFactory factory = producer.getConnectionFactory();
  85 + if (factory != null) {
  86 + ((RedissonConnectionFactory) factory).destroy();
104 } 87 }
105 } 88 }
106 89
@@ -119,7 +102,7 @@ public class IotRedisStreamMQDataBridgeExecute extends AbstractCacheableDataBrid @@ -119,7 +102,7 @@ public class IotRedisStreamMQDataBridgeExecute extends AbstractCacheableDataBrid
119 IotRedisStreamMQDataBridgeExecute action = new IotRedisStreamMQDataBridgeExecute(); 102 IotRedisStreamMQDataBridgeExecute action = new IotRedisStreamMQDataBridgeExecute();
120 103
121 // 2. 创建共享的配置 104 // 2. 创建共享的配置
122 - IotDataBridgeDO.RedisStreamMQConfig config = new IotDataBridgeDO.RedisStreamMQConfig(); 105 + IotDataBridgeRedisStreamMQConfig config = new IotDataBridgeRedisStreamMQConfig();
123 config.setHost("127.0.0.1"); 106 config.setHost("127.0.0.1");
124 config.setPort(6379); 107 config.setPort(6379);
125 config.setDatabase(0); 108 config.setDatabase(0);
@@ -140,11 +123,11 @@ public class IotRedisStreamMQDataBridgeExecute extends AbstractCacheableDataBrid @@ -140,11 +123,11 @@ public class IotRedisStreamMQDataBridgeExecute extends AbstractCacheableDataBrid
140 .build(); 123 .build();
141 124
142 // 4. 执行两次测试,验证缓存 125 // 4. 执行两次测试,验证缓存
143 - log.info("[main][第一次执行,应该会创建新的 RedisTemplate]");  
144 - action.executeRedisStream(message, config); 126 + log.info("[main][第一次执行,应该会创建新的 producer]");
  127 + action.execute(message, new IotDataBridgeDO().setType(action.getType()).setConfig(config));
145 128
146 - log.info("[main][第二次执行,应该会复用缓存的 RedisTemplate]");  
147 - action.executeRedisStream(message, config); 129 + log.info("[main][第二次执行,应该会复用缓存的 producer]");
  130 + action.execute(message, new IotDataBridgeDO().setType(action.getType()).setConfig(config));
148 } 131 }
149 132
150 } 133 }
151 \ No newline at end of file 134 \ 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/IotRocketMQDataBridgeExecute.java
1 package cn.iocoder.yudao.module.iot.service.rule.action.databridge; 1 package cn.iocoder.yudao.module.iot.service.rule.action.databridge;
2 2
  3 +import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.databridge.config.IotDataBridgeRocketMQConfig;
3 import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotDataBridgeDO; 4 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.enums.rule.IotDataBridgeTypeEnum;
5 import cn.iocoder.yudao.module.iot.mq.message.IotDeviceMessage; 6 import cn.iocoder.yudao.module.iot.mq.message.IotDeviceMessage;
6 import lombok.extern.slf4j.Slf4j; 7 import lombok.extern.slf4j.Slf4j;
7 import org.apache.rocketmq.client.producer.DefaultMQProducer; 8 import org.apache.rocketmq.client.producer.DefaultMQProducer;
@@ -9,6 +10,7 @@ import org.apache.rocketmq.client.producer.SendResult; @@ -9,6 +10,7 @@ import org.apache.rocketmq.client.producer.SendResult;
9 import org.apache.rocketmq.client.producer.SendStatus; 10 import org.apache.rocketmq.client.producer.SendStatus;
10 import org.apache.rocketmq.common.message.Message; 11 import org.apache.rocketmq.common.message.Message;
11 import org.apache.rocketmq.remoting.common.RemotingHelper; 12 import org.apache.rocketmq.remoting.common.RemotingHelper;
  13 +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
12 import org.springframework.stereotype.Component; 14 import org.springframework.stereotype.Component;
13 15
14 import java.time.LocalDateTime; 16 import java.time.LocalDateTime;
@@ -18,58 +20,49 @@ import java.time.LocalDateTime; @@ -18,58 +20,49 @@ import java.time.LocalDateTime;
18 * 20 *
19 * @author HUIHUI 21 * @author HUIHUI
20 */ 22 */
  23 +@ConditionalOnClass(name = "org.apache.rocketmq.client.producer.DefaultMQProducer")
21 @Component 24 @Component
22 @Slf4j 25 @Slf4j
23 -public class IotRocketMQDataBridgeExecute extends AbstractCacheableDataBridgeExecute { 26 +public class IotRocketMQDataBridgeExecute extends
  27 + AbstractCacheableDataBridgeExecute<IotDataBridgeRocketMQConfig, DefaultMQProducer> {
24 28
25 @Override 29 @Override
26 - public void execute(IotDeviceMessage message, IotDataBridgeDO dataBridge) {  
27 - // 1.1 校验数据桥梁的类型 == ROCKETMQ  
28 - if (!IotDataBridgTypeEnum.ROCKETMQ.getType().equals(dataBridge.getType())) {  
29 - return;  
30 - }  
31 - // 1.2 执行 RocketMQ 发送消息  
32 - executeRocketMQ(message, (IotDataBridgeDO.RocketMQConfig) dataBridge.getConfig()); 30 + public Integer getType() {
  31 + return IotDataBridgeTypeEnum.ROCKETMQ.getType();
33 } 32 }
34 33
35 - private void executeRocketMQ(IotDeviceMessage message, IotDataBridgeDO.RocketMQConfig config) {  
36 - try {  
37 - // 1. 获取或创建 Producer  
38 - DefaultMQProducer producer = (DefaultMQProducer) getProducer(config); 34 + @Override
  35 + public void execute0(IotDeviceMessage message, IotDataBridgeRocketMQConfig config) throws Exception {
  36 + // 1. 获取或创建 Producer
  37 + DefaultMQProducer producer = getProducer(config);
39 38
40 - // 2.1 创建消息对象,指定Topic、Tag和消息体  
41 - Message msg = new Message(  
42 - config.getTopic(),  
43 - config.getTags(),  
44 - message.toString().getBytes(RemotingHelper.DEFAULT_CHARSET)  
45 - );  
46 - // 2.2 发送同步消息并处理结果  
47 - SendResult sendResult = producer.send(msg);  
48 - // 2.3 处理发送结果  
49 - if (SendStatus.SEND_OK.equals(sendResult.getSendStatus())) {  
50 - log.info("[executeRocketMQ][message({}) config({}) 发送成功,结果({})]", message, config, sendResult);  
51 - } else {  
52 - log.error("[executeRocketMQ][message({}) config({}) 发送失败,结果({})]", message, config, sendResult);  
53 - }  
54 - } catch (Exception e) {  
55 - log.error("[executeRocketMQ][message({}) config({}) 发送异常]", message, config, e); 39 + // 2.1 创建消息对象,指定Topic、Tag和消息体
  40 + Message msg = new Message(
  41 + config.getTopic(),
  42 + config.getTags(),
  43 + message.toString().getBytes(RemotingHelper.DEFAULT_CHARSET)
  44 + );
  45 + // 2.2 发送同步消息并处理结果
  46 + SendResult sendResult = producer.send(msg);
  47 + // 2.3 处理发送结果
  48 + if (SendStatus.SEND_OK.equals(sendResult.getSendStatus())) {
  49 + log.info("[executeRocketMQ][message({}) config({}) 发送成功,结果({})]", message, config, sendResult);
  50 + } else {
  51 + log.error("[executeRocketMQ][message({}) config({}) 发送失败,结果({})]", message, config, sendResult);
56 } 52 }
57 } 53 }
58 54
59 @Override 55 @Override
60 - protected Object initProducer(Object config) throws Exception {  
61 - IotDataBridgeDO.RocketMQConfig rocketMQConfig = (IotDataBridgeDO.RocketMQConfig) config;  
62 - DefaultMQProducer producer = new DefaultMQProducer(rocketMQConfig.getGroup());  
63 - producer.setNamesrvAddr(rocketMQConfig.getNameServer()); 56 + protected DefaultMQProducer initProducer(IotDataBridgeRocketMQConfig config) throws Exception {
  57 + DefaultMQProducer producer = new DefaultMQProducer(config.getGroup());
  58 + producer.setNamesrvAddr(config.getNameServer());
64 producer.start(); 59 producer.start();
65 return producer; 60 return producer;
66 } 61 }
67 62
68 @Override 63 @Override
69 - protected void closeProducer(Object producer) {  
70 - if (producer instanceof DefaultMQProducer) {  
71 - ((DefaultMQProducer) producer).shutdown();  
72 - } 64 + protected void closeProducer(DefaultMQProducer producer) {
  65 + producer.shutdown();
73 } 66 }
74 67
75 // TODO @芋艿:测试代码,后续清理 68 // TODO @芋艿:测试代码,后续清理
@@ -78,7 +71,7 @@ public class IotRocketMQDataBridgeExecute extends AbstractCacheableDataBridgeExe @@ -78,7 +71,7 @@ public class IotRocketMQDataBridgeExecute extends AbstractCacheableDataBridgeExe
78 IotRocketMQDataBridgeExecute action = new IotRocketMQDataBridgeExecute(); 71 IotRocketMQDataBridgeExecute action = new IotRocketMQDataBridgeExecute();
79 72
80 // 2. 创建共享的配置 73 // 2. 创建共享的配置
81 - IotDataBridgeDO.RocketMQConfig config = new IotDataBridgeDO.RocketMQConfig(); 74 + IotDataBridgeRocketMQConfig config = new IotDataBridgeRocketMQConfig();
82 config.setNameServer("127.0.0.1:9876"); 75 config.setNameServer("127.0.0.1:9876");
83 config.setGroup("test-group"); 76 config.setGroup("test-group");
84 config.setTopic("test-topic"); 77 config.setTopic("test-topic");
@@ -99,10 +92,10 @@ public class IotRocketMQDataBridgeExecute extends AbstractCacheableDataBridgeExe @@ -99,10 +92,10 @@ public class IotRocketMQDataBridgeExecute extends AbstractCacheableDataBridgeExe
99 92
100 // 4. 执行两次测试,验证缓存 93 // 4. 执行两次测试,验证缓存
101 log.info("[main][第一次执行,应该会创建新的 producer]"); 94 log.info("[main][第一次执行,应该会创建新的 producer]");
102 - action.executeRocketMQ(message, config); 95 + action.execute(message, new IotDataBridgeDO().setType(action.getType()).setConfig(config));
103 96
104 log.info("[main][第二次执行,应该会复用缓存的 producer]"); 97 log.info("[main][第二次执行,应该会复用缓存的 producer]");
105 - action.executeRocketMQ(message, config); 98 + action.execute(message, new IotDataBridgeDO().setType(action.getType()).setConfig(config));
106 } 99 }
107 100
108 } 101 }
yudao-server/pom.xml
@@ -114,6 +114,19 @@ @@ -114,6 +114,19 @@
114 <artifactId>yudao-module-iot-biz</artifactId> 114 <artifactId>yudao-module-iot-biz</artifactId>
115 <version>${revision}</version> 115 <version>${revision}</version>
116 </dependency> 116 </dependency>
  117 + <!-- IoT 数据桥梁的执行器所需消息队列。如果您只需要使用 rocketmq 那么则注释掉其它消息队列即可 -->
  118 + <dependency>
  119 + <groupId>org.apache.rocketmq</groupId>
  120 + <artifactId>rocketmq-spring-boot-starter</artifactId>
  121 + </dependency>
  122 + <dependency>
  123 + <groupId>org.springframework.kafka</groupId>
  124 + <artifactId>spring-kafka</artifactId>
  125 + </dependency>
  126 + <dependency>
  127 + <groupId>org.springframework.boot</groupId>
  128 + <artifactId>spring-boot-starter-amqp</artifactId>
  129 + </dependency>
117 130
118 <!-- spring boot 配置所需依赖 --> 131 <!-- spring boot 配置所需依赖 -->
119 <dependency> 132 <dependency>