Commit 76ab64a255c311a354060eb2580f57a37aa29b7f
1 parent
0b16f167
【代码评审】IoT:物模型的管理
Showing
11 changed files
with
42 additions
and
83 deletions
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thingmodel/model/ThingModelEvent.java
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thingmodel/model/ThingModelParam.java
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thingmodel/model/ThingModelProperty.java
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thingmodel/model/ThingModelRespVO.java deleted
| 1 | -package cn.iocoder.yudao.module.iot.controller.admin.thingmodel.model; | ||
| 2 | - | ||
| 3 | -import lombok.*; | ||
| 4 | - | ||
| 5 | -import java.util.List; | ||
| 6 | - | ||
| 7 | -@Data | ||
| 8 | -@Builder | ||
| 9 | -@NoArgsConstructor | ||
| 10 | -@AllArgsConstructor | ||
| 11 | -@ToString | ||
| 12 | -public class ThingModelRespVO { | ||
| 13 | - | ||
| 14 | - /** | ||
| 15 | - * 产品编号 | ||
| 16 | - */ | ||
| 17 | - private Long id; | ||
| 18 | - | ||
| 19 | - /** | ||
| 20 | - * 产品标识 | ||
| 21 | - */ | ||
| 22 | - private String productKey; | ||
| 23 | - | ||
| 24 | - /** | ||
| 25 | - * 物模型 | ||
| 26 | - */ | ||
| 27 | - private Model model; | ||
| 28 | - | ||
| 29 | - /** | ||
| 30 | - * 物模型 | ||
| 31 | - */ | ||
| 32 | - @Data | ||
| 33 | - public static class Model { | ||
| 34 | - | ||
| 35 | - /** | ||
| 36 | - * 属性列表 | ||
| 37 | - */ | ||
| 38 | - private List<ThingModelProperty> properties; | ||
| 39 | - | ||
| 40 | - /** | ||
| 41 | - * 服务列表 | ||
| 42 | - */ | ||
| 43 | - private List<ThingModelService> services; | ||
| 44 | - | ||
| 45 | - /** | ||
| 46 | - * 事件列表 | ||
| 47 | - */ | ||
| 48 | - private List<ThingModelEvent> events; | ||
| 49 | - } | ||
| 50 | -} |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thingmodel/model/ThingModelService.java
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thingmodel/vo/IotThingModelListReqVO.java
| @@ -6,10 +6,15 @@ import io.swagger.v3.oas.annotations.media.Schema; | @@ -6,10 +6,15 @@ import io.swagger.v3.oas.annotations.media.Schema; | ||
| 6 | import jakarta.validation.constraints.NotNull; | 6 | import jakarta.validation.constraints.NotNull; |
| 7 | import lombok.Data; | 7 | import lombok.Data; |
| 8 | 8 | ||
| 9 | -@Schema(description = "管理后台 - IoT 产品物模型List Request VO") | 9 | +// TODO @puhui999:部分字段,可以用 cursor 加上 example |
| 10 | +@Schema(description = "管理后台 - IoT 产品物模型 List Request VO") | ||
| 10 | @Data | 11 | @Data |
| 11 | public class IotThingModelListReqVO { | 12 | public class IotThingModelListReqVO { |
| 12 | 13 | ||
| 14 | + @Schema(description = "产品编号", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 15 | + @NotNull(message = "产品编号不能为空") | ||
| 16 | + private Long productId; | ||
| 17 | + | ||
| 13 | @Schema(description = "功能标识") | 18 | @Schema(description = "功能标识") |
| 14 | private String identifier; | 19 | private String identifier; |
| 15 | 20 | ||
| @@ -20,8 +25,4 @@ public class IotThingModelListReqVO { | @@ -20,8 +25,4 @@ public class IotThingModelListReqVO { | ||
| 20 | @InEnum(IotThingModelTypeEnum.class) | 25 | @InEnum(IotThingModelTypeEnum.class) |
| 21 | private Integer type; | 26 | private Integer type; |
| 22 | 27 | ||
| 23 | - @Schema(description = "产品 ID", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 24 | - @NotNull(message = "产品 ID 不能为空") | ||
| 25 | - private Long productId; | ||
| 26 | - | ||
| 27 | } | 28 | } |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thingmodel/vo/IotThingModelPageReqVO.java
| @@ -9,12 +9,17 @@ import lombok.Data; | @@ -9,12 +9,17 @@ import lombok.Data; | ||
| 9 | import lombok.EqualsAndHashCode; | 9 | import lombok.EqualsAndHashCode; |
| 10 | import lombok.ToString; | 10 | import lombok.ToString; |
| 11 | 11 | ||
| 12 | +// TODO @puhui999:部分字段,可以用 cursor 加上 example | ||
| 12 | @Schema(description = "管理后台 - IoT 产品物模型分页 Request VO") | 13 | @Schema(description = "管理后台 - IoT 产品物模型分页 Request VO") |
| 13 | @Data | 14 | @Data |
| 14 | @EqualsAndHashCode(callSuper = true) | 15 | @EqualsAndHashCode(callSuper = true) |
| 15 | @ToString(callSuper = true) | 16 | @ToString(callSuper = true) |
| 16 | public class IotThingModelPageReqVO extends PageParam { | 17 | public class IotThingModelPageReqVO extends PageParam { |
| 17 | 18 | ||
| 19 | + @Schema(description = "产品编号", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 20 | + @NotNull(message = "产品编号不能为空") | ||
| 21 | + private Long productId; | ||
| 22 | + | ||
| 18 | @Schema(description = "功能标识") | 23 | @Schema(description = "功能标识") |
| 19 | private String identifier; | 24 | private String identifier; |
| 20 | 25 | ||
| @@ -25,8 +30,4 @@ public class IotThingModelPageReqVO extends PageParam { | @@ -25,8 +30,4 @@ public class IotThingModelPageReqVO extends PageParam { | ||
| 25 | @InEnum(IotThingModelTypeEnum.class) | 30 | @InEnum(IotThingModelTypeEnum.class) |
| 26 | private Integer type; | 31 | private Integer type; |
| 27 | 32 | ||
| 28 | - @Schema(description = "产品ID", requiredMode = Schema.RequiredMode.REQUIRED) | ||
| 29 | - @NotNull(message = "产品ID不能为空") | ||
| 30 | - private Long productId; | ||
| 31 | - | ||
| 32 | } | 33 | } |
| 33 | \ No newline at end of file | 34 | \ No newline at end of file |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thingmodel/vo/IotThingModelRespVO.java
| @@ -10,6 +10,7 @@ import lombok.Data; | @@ -10,6 +10,7 @@ import lombok.Data; | ||
| 10 | 10 | ||
| 11 | import java.time.LocalDateTime; | 11 | import java.time.LocalDateTime; |
| 12 | 12 | ||
| 13 | +// TODO @puhui999:部分字段,可以用 cursor 加上 example | ||
| 13 | @Schema(description = "管理后台 - IoT 产品物模型 Response VO") | 14 | @Schema(description = "管理后台 - IoT 产品物模型 Response VO") |
| 14 | @Data | 15 | @Data |
| 15 | @ExcelIgnoreUnannotated | 16 | @ExcelIgnoreUnannotated |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thingmodel/vo/IotThingModelSaveReqVO.java
| @@ -10,6 +10,7 @@ import jakarta.validation.constraints.NotEmpty; | @@ -10,6 +10,7 @@ import jakarta.validation.constraints.NotEmpty; | ||
| 10 | import jakarta.validation.constraints.NotNull; | 10 | import jakarta.validation.constraints.NotNull; |
| 11 | import lombok.Data; | 11 | import lombok.Data; |
| 12 | 12 | ||
| 13 | +// TODO @puhui999:部分字段,可以用 cursor 加上 example | ||
| 13 | @Schema(description = "管理后台 - IoT 产品物模型新增/修改 Request VO") | 14 | @Schema(description = "管理后台 - IoT 产品物模型新增/修改 Request VO") |
| 14 | @Data | 15 | @Data |
| 15 | public class IotThingModelSaveReqVO { | 16 | public class IotThingModelSaveReqVO { |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thingmodel/IotThingModelService.java
| @@ -79,4 +79,5 @@ public interface IotThingModelService { | @@ -79,4 +79,5 @@ public interface IotThingModelService { | ||
| 79 | * @return 产品物模型列表 | 79 | * @return 产品物模型列表 |
| 80 | */ | 80 | */ |
| 81 | List<IotThingModelDO> getThingModelList(IotThingModelListReqVO reqVO); | 81 | List<IotThingModelDO> getThingModelList(IotThingModelListReqVO reqVO); |
| 82 | + | ||
| 82 | } | 83 | } |
| 83 | \ No newline at end of file | 84 | \ No newline at end of file |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thingmodel/IotThingModelServiceImpl.java
| @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.iot.service.thingmodel; | @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.iot.service.thingmodel; | ||
| 2 | 2 | ||
| 3 | import cn.hutool.core.collection.CollUtil; | 3 | import cn.hutool.core.collection.CollUtil; |
| 4 | import cn.hutool.core.util.ObjectUtil; | 4 | import cn.hutool.core.util.ObjectUtil; |
| 5 | +import cn.hutool.core.util.StrUtil; | ||
| 5 | import cn.hutool.extra.spring.SpringUtil; | 6 | import cn.hutool.extra.spring.SpringUtil; |
| 6 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 7 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 7 | import cn.iocoder.yudao.framework.common.util.object.BeanUtils; | 8 | import cn.iocoder.yudao.framework.common.util.object.BeanUtils; |
| @@ -54,29 +55,26 @@ public class IotThingModelServiceImpl implements IotThingModelService { | @@ -54,29 +55,26 @@ public class IotThingModelServiceImpl implements IotThingModelService { | ||
| 54 | @Override | 55 | @Override |
| 55 | @Transactional(rollbackFor = Exception.class) | 56 | @Transactional(rollbackFor = Exception.class) |
| 56 | public Long createThingModel(IotThingModelSaveReqVO createReqVO) { | 57 | public Long createThingModel(IotThingModelSaveReqVO createReqVO) { |
| 57 | - // 1. 校验功能标识符在同一产品下是否唯一 | 58 | + // 1.1 校验功能标识符在同一产品下是否唯一 |
| 58 | validateIdentifierUnique(createReqVO.getProductId(), createReqVO.getIdentifier()); | 59 | validateIdentifierUnique(createReqVO.getProductId(), createReqVO.getIdentifier()); |
| 59 | - | ||
| 60 | - // 2. 功能名称在同一产品下是否唯一 | 60 | + // 1.2 功能名称在同一产品下是否唯一 |
| 61 | validateNameUnique(createReqVO.getProductId(), createReqVO.getName()); | 61 | validateNameUnique(createReqVO.getProductId(), createReqVO.getName()); |
| 62 | - | ||
| 63 | - // 3. 系统保留字段,不能用于标识符定义 | 62 | + // 1.3 系统保留字段,不能用于标识符定义 |
| 64 | validateNotDefaultEventAndService(createReqVO.getIdentifier()); | 63 | validateNotDefaultEventAndService(createReqVO.getIdentifier()); |
| 65 | - | ||
| 66 | - // 4. 校验产品状态,发布状态下,不允许新增功能 | 64 | + // 1.4 校验产品状态,发布状态下,不允许新增功能 |
| 67 | validateProductStatus(createReqVO.getProductId()); | 65 | validateProductStatus(createReqVO.getProductId()); |
| 68 | 66 | ||
| 69 | - // 5. 插入数据库 | 67 | + // 2. 插入数据库 |
| 70 | IotThingModelDO thingModel = IotThingModelConvert.INSTANCE.convert(createReqVO); | 68 | IotThingModelDO thingModel = IotThingModelConvert.INSTANCE.convert(createReqVO); |
| 71 | thingModelMapper.insert(thingModel); | 69 | thingModelMapper.insert(thingModel); |
| 72 | 70 | ||
| 73 | - // 6. 如果创建的是属性,需要更新默认的事件和服务 | 71 | + // 3. 如果创建的是属性,需要更新默认的事件和服务 |
| 74 | if (Objects.equals(createReqVO.getType(), IotThingModelTypeEnum.PROPERTY.getType())) { | 72 | if (Objects.equals(createReqVO.getType(), IotThingModelTypeEnum.PROPERTY.getType())) { |
| 75 | createDefaultEventsAndServices(createReqVO.getProductId(), createReqVO.getProductKey()); | 73 | createDefaultEventsAndServices(createReqVO.getProductId(), createReqVO.getProductKey()); |
| 76 | } | 74 | } |
| 77 | // TODO @puhui999: 服务和事件的情况 method 怎么设置?在前端设置还是后端设置? | 75 | // TODO @puhui999: 服务和事件的情况 method 怎么设置?在前端设置还是后端设置? |
| 78 | 76 | ||
| 79 | - // 7. 删除缓存 | 77 | + // 4. 删除缓存 |
| 80 | deleteThingModelListCache(createReqVO.getProductKey()); | 78 | deleteThingModelListCache(createReqVO.getProductKey()); |
| 81 | return thingModel.getId(); | 79 | return thingModel.getId(); |
| 82 | } | 80 | } |
| @@ -84,38 +82,35 @@ public class IotThingModelServiceImpl implements IotThingModelService { | @@ -84,38 +82,35 @@ public class IotThingModelServiceImpl implements IotThingModelService { | ||
| 84 | @Override | 82 | @Override |
| 85 | @Transactional(rollbackFor = Exception.class) | 83 | @Transactional(rollbackFor = Exception.class) |
| 86 | public void updateThingModel(IotThingModelSaveReqVO updateReqVO) { | 84 | public void updateThingModel(IotThingModelSaveReqVO updateReqVO) { |
| 87 | - // 1. 校验功能是否存在 | 85 | + // 1.1 校验功能是否存在 |
| 88 | validateProductThingModelMapperExists(updateReqVO.getId()); | 86 | validateProductThingModelMapperExists(updateReqVO.getId()); |
| 89 | - | ||
| 90 | - // 2. 校验功能标识符是否唯一 | 87 | + // 1.2 校验功能标识符是否唯一 |
| 91 | validateIdentifierUniqueForUpdate(updateReqVO.getId(), updateReqVO.getProductId(), updateReqVO.getIdentifier()); | 88 | validateIdentifierUniqueForUpdate(updateReqVO.getId(), updateReqVO.getProductId(), updateReqVO.getIdentifier()); |
| 92 | - | ||
| 93 | - // 3. 校验产品状态,发布状态下,不允许操作功能 | 89 | + // 1.3 校验产品状态,发布状态下,不允许操作功能 |
| 94 | validateProductStatus(updateReqVO.getProductId()); | 90 | validateProductStatus(updateReqVO.getProductId()); |
| 95 | 91 | ||
| 96 | - // 4. 更新数据库 | 92 | + // 2. 更新数据库 |
| 97 | IotThingModelDO thingModel = IotThingModelConvert.INSTANCE.convert(updateReqVO); | 93 | IotThingModelDO thingModel = IotThingModelConvert.INSTANCE.convert(updateReqVO); |
| 98 | thingModelMapper.updateById(thingModel); | 94 | thingModelMapper.updateById(thingModel); |
| 99 | 95 | ||
| 100 | - // 5. 如果更新的是属性,需要更新默认的事件和服务 | 96 | + // 3. 如果更新的是属性,需要更新默认的事件和服务 |
| 101 | if (Objects.equals(updateReqVO.getType(), IotThingModelTypeEnum.PROPERTY.getType())) { | 97 | if (Objects.equals(updateReqVO.getType(), IotThingModelTypeEnum.PROPERTY.getType())) { |
| 102 | createDefaultEventsAndServices(updateReqVO.getProductId(), updateReqVO.getProductKey()); | 98 | createDefaultEventsAndServices(updateReqVO.getProductId(), updateReqVO.getProductKey()); |
| 103 | } | 99 | } |
| 104 | 100 | ||
| 105 | - // 6. 删除缓存 | 101 | + // 4. 删除缓存 |
| 106 | deleteThingModelListCache(updateReqVO.getProductKey()); | 102 | deleteThingModelListCache(updateReqVO.getProductKey()); |
| 107 | } | 103 | } |
| 108 | 104 | ||
| 109 | @Override | 105 | @Override |
| 110 | @Transactional(rollbackFor = Exception.class) | 106 | @Transactional(rollbackFor = Exception.class) |
| 111 | public void deleteThingModel(Long id) { | 107 | public void deleteThingModel(Long id) { |
| 112 | - // 1. 校验功能是否存在 | 108 | + // 1.1 校验功能是否存在 |
| 113 | IotThingModelDO thingModel = thingModelMapper.selectById(id); | 109 | IotThingModelDO thingModel = thingModelMapper.selectById(id); |
| 114 | if (thingModel == null) { | 110 | if (thingModel == null) { |
| 115 | throw exception(THING_MODEL_NOT_EXISTS); | 111 | throw exception(THING_MODEL_NOT_EXISTS); |
| 116 | } | 112 | } |
| 117 | - | ||
| 118 | - // 3. 校验产品状态,发布状态下,不允许操作功能 | 113 | + // 1.2 校验产品状态,发布状态下,不允许操作功能 |
| 119 | validateProductStatus(thingModel.getProductId()); | 114 | validateProductStatus(thingModel.getProductId()); |
| 120 | 115 | ||
| 121 | // 2. 删除功能 | 116 | // 2. 删除功能 |
| @@ -168,6 +163,7 @@ public class IotThingModelServiceImpl implements IotThingModelService { | @@ -168,6 +163,7 @@ public class IotThingModelServiceImpl implements IotThingModelService { | ||
| 168 | } | 163 | } |
| 169 | } | 164 | } |
| 170 | 165 | ||
| 166 | + // TODO @puhui999:这个方法,和 validateIdentifierUnique 可以融合下 | ||
| 171 | private void validateIdentifierUniqueForUpdate(Long id, Long productId, String identifier) { | 167 | private void validateIdentifierUniqueForUpdate(Long id, Long productId, String identifier) { |
| 172 | IotThingModelDO thingModel = thingModelMapper.selectByProductIdAndIdentifier(productId, identifier); | 168 | IotThingModelDO thingModel = thingModelMapper.selectByProductIdAndIdentifier(productId, identifier); |
| 173 | if (thingModel != null && ObjectUtil.notEqual(thingModel.getId(), id)) { | 169 | if (thingModel != null && ObjectUtil.notEqual(thingModel.getId(), id)) { |
| @@ -176,15 +172,16 @@ public class IotThingModelServiceImpl implements IotThingModelService { | @@ -176,15 +172,16 @@ public class IotThingModelServiceImpl implements IotThingModelService { | ||
| 176 | } | 172 | } |
| 177 | 173 | ||
| 178 | private void validateProductStatus(Long createReqVO) { | 174 | private void validateProductStatus(Long createReqVO) { |
| 179 | - IotProductDO product = productService.getProduct(createReqVO); | 175 | + IotProductDO product = productService.validateProductExists(createReqVO); |
| 180 | if (Objects.equals(product.getStatus(), IotProductStatusEnum.PUBLISHED.getStatus())) { | 176 | if (Objects.equals(product.getStatus(), IotProductStatusEnum.PUBLISHED.getStatus())) { |
| 181 | throw exception(PRODUCT_STATUS_NOT_ALLOW_THING_MODEL); | 177 | throw exception(PRODUCT_STATUS_NOT_ALLOW_THING_MODEL); |
| 182 | } | 178 | } |
| 183 | } | 179 | } |
| 184 | 180 | ||
| 181 | + // TODO @芋艿:在 review 下 | ||
| 185 | private void validateNotDefaultEventAndService(String identifier) { | 182 | private void validateNotDefaultEventAndService(String identifier) { |
| 186 | - // set, get, post, property, event, time, value 是系统保留字段,不能用于标识符定义 | ||
| 187 | - if (CollUtil.containsAny(Arrays.asList("set", "get", "post", "property", "event", "time", "value"), Collections.singletonList(identifier))) { | 183 | + // 系统保留字段,不能用于标识符定义 |
| 184 | + if (StrUtil.equalsAny(identifier, "set", "get", "post", "property", "event", "time", "value")) { | ||
| 188 | throw exception(THING_MODEL_IDENTIFIER_INVALID); | 185 | throw exception(THING_MODEL_IDENTIFIER_INVALID); |
| 189 | } | 186 | } |
| 190 | } | 187 | } |
| @@ -205,6 +202,9 @@ public class IotThingModelServiceImpl implements IotThingModelService { | @@ -205,6 +202,9 @@ public class IotThingModelServiceImpl implements IotThingModelService { | ||
| 205 | 202 | ||
| 206 | /** | 203 | /** |
| 207 | * 创建默认的事件和服务 | 204 | * 创建默认的事件和服务 |
| 205 | + * | ||
| 206 | + * @param productId 产品编号 | ||
| 207 | + * @param productKey 产品标识 | ||
| 208 | */ | 208 | */ |
| 209 | public void createDefaultEventsAndServices(Long productId, String productKey) { | 209 | public void createDefaultEventsAndServices(Long productId, String productKey) { |
| 210 | // 1. 获取当前属性列表 | 210 | // 1. 获取当前属性列表 |