Commit a364153d4a9a34375151d8527a5ad54ed60f6c22
1 parent
7745035f
【功能优化】IoT:device 和 thingmodel 读取增加缓存
Showing
8 changed files
with
115 additions
and
32 deletions
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/thingmodel/IotThingModelMapper.java
| @@ -49,6 +49,10 @@ public interface IotThingModelMapper extends BaseMapperX<IotThingModelDO> { | @@ -49,6 +49,10 @@ public interface IotThingModelMapper extends BaseMapperX<IotThingModelDO> { | ||
| 49 | return selectList(IotThingModelDO::getProductId, productId); | 49 | return selectList(IotThingModelDO::getProductId, productId); |
| 50 | } | 50 | } |
| 51 | 51 | ||
| 52 | + default List<IotThingModelDO> selectListByProductKey(String productKey) { | ||
| 53 | + return selectList(IotThingModelDO::getProductKey, productKey); | ||
| 54 | + } | ||
| 55 | + | ||
| 52 | default List<IotThingModelDO> selectListByProductIdAndType(Long productId, Integer type) { | 56 | default List<IotThingModelDO> selectListByProductIdAndType(Long productId, Integer type) { |
| 53 | return selectList(IotThingModelDO::getProductId, productId, | 57 | return selectList(IotThingModelDO::getProductId, productId, |
| 54 | IotThingModelDO::getType, type); | 58 | IotThingModelDO::getType, type); |
| @@ -68,8 +72,4 @@ public interface IotThingModelMapper extends BaseMapperX<IotThingModelDO> { | @@ -68,8 +72,4 @@ public interface IotThingModelMapper extends BaseMapperX<IotThingModelDO> { | ||
| 68 | IotThingModelDO::getName, name); | 72 | IotThingModelDO::getName, name); |
| 69 | } | 73 | } |
| 70 | 74 | ||
| 71 | - default List<IotThingModelDO> selectListByProductKey(String productKey) { | ||
| 72 | - return selectList(IotThingModelDO::getProductKey, productKey); | ||
| 73 | - } | ||
| 74 | - | ||
| 75 | } | 75 | } |
| 76 | \ No newline at end of file | 76 | \ No newline at end of file |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/redis/RedisKeyConstants.java
| @@ -10,7 +10,7 @@ import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDevicePropertyDO; | @@ -10,7 +10,7 @@ import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDevicePropertyDO; | ||
| 10 | public interface RedisKeyConstants { | 10 | public interface RedisKeyConstants { |
| 11 | 11 | ||
| 12 | /** | 12 | /** |
| 13 | - * 设备属性数据缓存,采用 HASH 结构 | 13 | + * 设备属性的数据缓存,采用 HASH 结构 |
| 14 | * <p> | 14 | * <p> |
| 15 | * KEY 格式:device_property:{deviceKey} | 15 | * KEY 格式:device_property:{deviceKey} |
| 16 | * HASH KEY:identifier 属性标识 | 16 | * HASH KEY:identifier 属性标识 |
| @@ -26,4 +26,20 @@ public interface RedisKeyConstants { | @@ -26,4 +26,20 @@ public interface RedisKeyConstants { | ||
| 26 | */ | 26 | */ |
| 27 | String DEVICE_REPORT_TIME = "device_report_time"; | 27 | String DEVICE_REPORT_TIME = "device_report_time"; |
| 28 | 28 | ||
| 29 | + /** | ||
| 30 | + * 设备信息的数据缓存,使用 Spring Cache 操作 | ||
| 31 | + * | ||
| 32 | + * KEY 格式:device_${productKey}_${deviceKey} | ||
| 33 | + * VALUE 数据类型:String(JSON) | ||
| 34 | + */ | ||
| 35 | + String DEVICE = "device"; | ||
| 36 | + | ||
| 37 | + /** | ||
| 38 | + * 物模型的数据缓存,使用 Spring Cache 操作 | ||
| 39 | + * | ||
| 40 | + * KEY 格式:thing_model_${productKey} | ||
| 41 | + * VALUE 数据类型:String 数组(JSON),即 {@link cn.iocoder.yudao.module.iot.dal.dataobject.thingmodel.IotThingModelDO} 列表 | ||
| 42 | + */ | ||
| 43 | + String THING_MODEL_LIST = "thing_model_list"; | ||
| 44 | + | ||
| 29 | } | 45 | } |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceService.java
| @@ -113,15 +113,16 @@ public interface IotDeviceService { | @@ -113,15 +113,16 @@ public interface IotDeviceService { | ||
| 113 | */ | 113 | */ |
| 114 | Long getDeviceCountByGroupId(Long groupId); | 114 | Long getDeviceCountByGroupId(Long groupId); |
| 115 | 115 | ||
| 116 | - // TODO @芋艿:增加缓存 | ||
| 117 | /** | 116 | /** |
| 118 | - * 根据产品 key 和设备名称,获得设备信息 | 117 | + * 【缓存】根据产品 key 和设备名称,获得设备信息 |
| 118 | + * | ||
| 119 | + * 注意:该方法会忽略租户信息,所以调用时,需要确认会不会有跨租户访问的风险!!! | ||
| 119 | * | 120 | * |
| 120 | * @param productKey 产品 key | 121 | * @param productKey 产品 key |
| 121 | * @param deviceName 设备名称 | 122 | * @param deviceName 设备名称 |
| 122 | * @return 设备信息 | 123 | * @return 设备信息 |
| 123 | */ | 124 | */ |
| 124 | - IotDeviceDO getDeviceByProductKeyAndDeviceName(String productKey, String deviceName); | 125 | + IotDeviceDO getDeviceByProductKeyAndDeviceNameFromCache(String productKey, String deviceName); |
| 125 | 126 | ||
| 126 | /** | 127 | /** |
| 127 | * 导入设备 | 128 | * 导入设备 |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceServiceImpl.java
| @@ -4,22 +4,27 @@ import cn.hutool.core.collection.CollUtil; | @@ -4,22 +4,27 @@ import cn.hutool.core.collection.CollUtil; | ||
| 4 | import cn.hutool.core.util.IdUtil; | 4 | import cn.hutool.core.util.IdUtil; |
| 5 | import cn.hutool.core.util.RandomUtil; | 5 | import cn.hutool.core.util.RandomUtil; |
| 6 | import cn.hutool.core.util.StrUtil; | 6 | import cn.hutool.core.util.StrUtil; |
| 7 | +import cn.hutool.extra.spring.SpringUtil; | ||
| 7 | import cn.iocoder.yudao.framework.common.exception.ServiceException; | 8 | import cn.iocoder.yudao.framework.common.exception.ServiceException; |
| 8 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 9 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 9 | import cn.iocoder.yudao.framework.common.util.object.BeanUtils; | 10 | import cn.iocoder.yudao.framework.common.util.object.BeanUtils; |
| 10 | import cn.iocoder.yudao.framework.common.util.validation.ValidationUtils; | 11 | import cn.iocoder.yudao.framework.common.util.validation.ValidationUtils; |
| 12 | +import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore; | ||
| 11 | import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils; | 13 | import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils; |
| 12 | import cn.iocoder.yudao.module.iot.controller.admin.device.vo.device.*; | 14 | import cn.iocoder.yudao.module.iot.controller.admin.device.vo.device.*; |
| 13 | import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO; | 15 | import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO; |
| 14 | import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceGroupDO; | 16 | import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceGroupDO; |
| 15 | import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO; | 17 | import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO; |
| 16 | import cn.iocoder.yudao.module.iot.dal.mysql.device.IotDeviceMapper; | 18 | import cn.iocoder.yudao.module.iot.dal.mysql.device.IotDeviceMapper; |
| 19 | +import cn.iocoder.yudao.module.iot.dal.redis.RedisKeyConstants; | ||
| 17 | import cn.iocoder.yudao.module.iot.enums.device.IotDeviceStatusEnum; | 20 | import cn.iocoder.yudao.module.iot.enums.device.IotDeviceStatusEnum; |
| 18 | import cn.iocoder.yudao.module.iot.enums.product.IotProductDeviceTypeEnum; | 21 | import cn.iocoder.yudao.module.iot.enums.product.IotProductDeviceTypeEnum; |
| 19 | import cn.iocoder.yudao.module.iot.service.product.IotProductService; | 22 | import cn.iocoder.yudao.module.iot.service.product.IotProductService; |
| 20 | import jakarta.annotation.Resource; | 23 | import jakarta.annotation.Resource; |
| 21 | import jakarta.validation.ConstraintViolationException; | 24 | import jakarta.validation.ConstraintViolationException; |
| 22 | import lombok.extern.slf4j.Slf4j; | 25 | import lombok.extern.slf4j.Slf4j; |
| 26 | +import org.springframework.cache.annotation.CacheEvict; | ||
| 27 | +import org.springframework.cache.annotation.Cacheable; | ||
| 23 | import org.springframework.context.annotation.Lazy; | 28 | import org.springframework.context.annotation.Lazy; |
| 24 | import org.springframework.stereotype.Service; | 29 | import org.springframework.stereotype.Service; |
| 25 | import org.springframework.transaction.annotation.Transactional; | 30 | import org.springframework.transaction.annotation.Transactional; |
| @@ -78,6 +83,7 @@ public class IotDeviceServiceImpl implements IotDeviceService { | @@ -78,6 +83,7 @@ public class IotDeviceServiceImpl implements IotDeviceService { | ||
| 78 | deviceGroupService.validateDeviceGroupExists(createReqVO.getGroupIds()); | 83 | deviceGroupService.validateDeviceGroupExists(createReqVO.getGroupIds()); |
| 79 | 84 | ||
| 80 | // 2.1 转换 VO 为 DO | 85 | // 2.1 转换 VO 为 DO |
| 86 | + // TODO @芋艿:state 相关的参数。另外,到底叫 state,还是 status 好! | ||
| 81 | IotDeviceDO device = BeanUtils.toBean(createReqVO, IotDeviceDO.class, o -> { | 87 | IotDeviceDO device = BeanUtils.toBean(createReqVO, IotDeviceDO.class, o -> { |
| 82 | o.setProductKey(product.getProductKey()).setDeviceType(product.getDeviceType()); | 88 | o.setProductKey(product.getProductKey()).setDeviceType(product.getDeviceType()); |
| 83 | // 生成并设置必要的字段 | 89 | // 生成并设置必要的字段 |
| @@ -109,6 +115,9 @@ public class IotDeviceServiceImpl implements IotDeviceService { | @@ -109,6 +115,9 @@ public class IotDeviceServiceImpl implements IotDeviceService { | ||
| 109 | // 2. 更新到数据库 | 115 | // 2. 更新到数据库 |
| 110 | IotDeviceDO updateObj = BeanUtils.toBean(updateReqVO, IotDeviceDO.class); | 116 | IotDeviceDO updateObj = BeanUtils.toBean(updateReqVO, IotDeviceDO.class); |
| 111 | deviceMapper.updateById(updateObj); | 117 | deviceMapper.updateById(updateObj); |
| 118 | + | ||
| 119 | + // 3. 清空对应缓存 | ||
| 120 | + deleteDeviceCache(device); | ||
| 112 | } | 121 | } |
| 113 | 122 | ||
| 114 | @Override | 123 | @Override |
| @@ -125,6 +134,9 @@ public class IotDeviceServiceImpl implements IotDeviceService { | @@ -125,6 +134,9 @@ public class IotDeviceServiceImpl implements IotDeviceService { | ||
| 125 | // 3. 更新设备分组 | 134 | // 3. 更新设备分组 |
| 126 | deviceMapper.updateBatch(convertList(devices, device -> new IotDeviceDO() | 135 | deviceMapper.updateBatch(convertList(devices, device -> new IotDeviceDO() |
| 127 | .setId(device.getId()).setGroupIds(updateReqVO.getGroupIds()))); | 136 | .setId(device.getId()).setGroupIds(updateReqVO.getGroupIds()))); |
| 137 | + | ||
| 138 | + // 4. 清空对应缓存 | ||
| 139 | + deleteDeviceCache(devices); | ||
| 128 | } | 140 | } |
| 129 | 141 | ||
| 130 | @Override | 142 | @Override |
| @@ -138,6 +150,9 @@ public class IotDeviceServiceImpl implements IotDeviceService { | @@ -138,6 +150,9 @@ public class IotDeviceServiceImpl implements IotDeviceService { | ||
| 138 | 150 | ||
| 139 | // 2. 删除设备 | 151 | // 2. 删除设备 |
| 140 | deviceMapper.deleteById(id); | 152 | deviceMapper.deleteById(id); |
| 153 | + | ||
| 154 | + // 3. 清空对应缓存 | ||
| 155 | + deleteDeviceCache(device); | ||
| 141 | } | 156 | } |
| 142 | 157 | ||
| 143 | @Override | 158 | @Override |
| @@ -160,6 +175,9 @@ public class IotDeviceServiceImpl implements IotDeviceService { | @@ -160,6 +175,9 @@ public class IotDeviceServiceImpl implements IotDeviceService { | ||
| 160 | 175 | ||
| 161 | // 2. 删除设备 | 176 | // 2. 删除设备 |
| 162 | deviceMapper.deleteByIds(ids); | 177 | deviceMapper.deleteByIds(ids); |
| 178 | + | ||
| 179 | + // 3. 清空对应缓存 | ||
| 180 | + deleteDeviceCache(devices); | ||
| 163 | } | 181 | } |
| 164 | 182 | ||
| 165 | /** | 183 | /** |
| @@ -213,6 +231,8 @@ public class IotDeviceServiceImpl implements IotDeviceService { | @@ -213,6 +231,8 @@ public class IotDeviceServiceImpl implements IotDeviceService { | ||
| 213 | 231 | ||
| 214 | @Override | 232 | @Override |
| 215 | public void updateDeviceStatus(IotDeviceStatusUpdateReqVO updateReqVO) { | 233 | public void updateDeviceStatus(IotDeviceStatusUpdateReqVO updateReqVO) { |
| 234 | + // TODO @芋艿:state 相关的参数。另外,到底叫 state,还是 status 好! | ||
| 235 | + // TODO @芋艿:各种时间,需要 check 下,优化处理下! | ||
| 216 | // 1. 校验存在 | 236 | // 1. 校验存在 |
| 217 | IotDeviceDO device = validateDeviceExists(updateReqVO.getId()); | 237 | IotDeviceDO device = validateDeviceExists(updateReqVO.getId()); |
| 218 | 238 | ||
| @@ -233,6 +253,9 @@ public class IotDeviceServiceImpl implements IotDeviceService { | @@ -233,6 +253,9 @@ public class IotDeviceServiceImpl implements IotDeviceService { | ||
| 233 | } | 253 | } |
| 234 | // 2.3 更新到数据库 | 254 | // 2.3 更新到数据库 |
| 235 | deviceMapper.updateById(updateDevice); | 255 | deviceMapper.updateById(updateDevice); |
| 256 | + | ||
| 257 | + // 3. 清空对应缓存 | ||
| 258 | + deleteDeviceCache(device); | ||
| 236 | } | 259 | } |
| 237 | 260 | ||
| 238 | @Override | 261 | @Override |
| @@ -246,7 +269,9 @@ public class IotDeviceServiceImpl implements IotDeviceService { | @@ -246,7 +269,9 @@ public class IotDeviceServiceImpl implements IotDeviceService { | ||
| 246 | } | 269 | } |
| 247 | 270 | ||
| 248 | @Override | 271 | @Override |
| 249 | - public IotDeviceDO getDeviceByProductKeyAndDeviceName(String productKey, String deviceName) { | 272 | + @TenantIgnore |
| 273 | + @Cacheable(value = RedisKeyConstants.DEVICE, key = "#productKey + '_' + #deviceName", unless = "#result == null") | ||
| 274 | + public IotDeviceDO getDeviceByProductKeyAndDeviceNameFromCache(String productKey, String deviceName) { | ||
| 250 | return deviceMapper.selectByProductKeyAndDeviceName(productKey, deviceName); | 275 | return deviceMapper.selectByProductKeyAndDeviceName(productKey, deviceName); |
| 251 | } | 276 | } |
| 252 | 277 | ||
| @@ -367,4 +392,20 @@ public class IotDeviceServiceImpl implements IotDeviceService { | @@ -367,4 +392,20 @@ public class IotDeviceServiceImpl implements IotDeviceService { | ||
| 367 | return respVO; | 392 | return respVO; |
| 368 | } | 393 | } |
| 369 | 394 | ||
| 395 | + private void deleteDeviceCache(IotDeviceDO device) { | ||
| 396 | + // 保证在 @CacheEvict 之前,忽略租户 | ||
| 397 | + TenantUtils.executeIgnore(() -> getSelf().deleteDeviceCache0(device)); | ||
| 398 | + } | ||
| 399 | + | ||
| 400 | + private void deleteDeviceCache(List<IotDeviceDO> devices) { | ||
| 401 | + devices.forEach(this::deleteDeviceCache); | ||
| 402 | + } | ||
| 403 | + | ||
| 404 | + @CacheEvict(value = RedisKeyConstants.DEVICE, key = "#device.productKey + '_' + #device.deviceName") | ||
| 405 | + public void deleteDeviceCache0(IotDeviceDO device) {} | ||
| 406 | + | ||
| 407 | + private IotDeviceServiceImpl getSelf() { | ||
| 408 | + return SpringUtil.getBean(getClass()); | ||
| 409 | + } | ||
| 410 | + | ||
| 370 | } | 411 | } |
| 371 | \ No newline at end of file | 412 | \ No newline at end of file |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/data/IotDevicePropertyServiceImpl.java
| @@ -118,21 +118,21 @@ public class IotDevicePropertyServiceImpl implements IotDevicePropertyService { | @@ -118,21 +118,21 @@ public class IotDevicePropertyServiceImpl implements IotDevicePropertyService { | ||
| 118 | } | 118 | } |
| 119 | 119 | ||
| 120 | @Override | 120 | @Override |
| 121 | - @TenantIgnore // TODO @芋艿:租户的缓存问题,需要考虑下。因为会存在一会又 tenantId,一会没有! | 121 | + @TenantIgnore |
| 122 | public void saveDeviceProperty(IotDeviceMessage message) { | 122 | public void saveDeviceProperty(IotDeviceMessage message) { |
| 123 | if (!(message.getData() instanceof Map)) { | 123 | if (!(message.getData() instanceof Map)) { |
| 124 | log.error("[saveDeviceProperty][消息内容({}) 的 data 类型不正确]", message); | 124 | log.error("[saveDeviceProperty][消息内容({}) 的 data 类型不正确]", message); |
| 125 | return; | 125 | return; |
| 126 | } | 126 | } |
| 127 | // 1. 获得设备信息 | 127 | // 1. 获得设备信息 |
| 128 | - IotDeviceDO device = deviceService.getDeviceByProductKeyAndDeviceName(message.getProductKey(), message.getDeviceName()); | 128 | + IotDeviceDO device = deviceService.getDeviceByProductKeyAndDeviceNameFromCache(message.getProductKey(), message.getDeviceName()); |
| 129 | if (device == null) { | 129 | if (device == null) { |
| 130 | log.error("[saveDeviceProperty][消息({}) 对应的设备不存在]", message); | 130 | log.error("[saveDeviceProperty][消息({}) 对应的设备不存在]", message); |
| 131 | return; | 131 | return; |
| 132 | } | 132 | } |
| 133 | 133 | ||
| 134 | // 2. 根据物模型,拼接合法的属性 | 134 | // 2. 根据物模型,拼接合法的属性 |
| 135 | - List<IotThingModelDO> thingModels = thingModelService.getThingModelListByProductId(device.getProductId()); | 135 | + List<IotThingModelDO> thingModels = thingModelService.getThingModelListByProductKeyFromCache(device.getProductKey()); |
| 136 | Map<String, Object> properties = new HashMap<>(); | 136 | Map<String, Object> properties = new HashMap<>(); |
| 137 | ((Map<?, ?>) message.getData()).forEach((key, value) -> { | 137 | ((Map<?, ?>) message.getData()).forEach((key, value) -> { |
| 138 | if (CollUtil.findOne(thingModels, thingModel -> thingModel.getIdentifier().equals(key)) == null) { | 138 | if (CollUtil.findOne(thingModels, thingModel -> thingModel.getIdentifier().equals(key)) == null) { |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/upstream/IotDeviceUpstreamServiceImpl.java
| @@ -3,7 +3,6 @@ package cn.iocoder.yudao.module.iot.service.device.upstream; | @@ -3,7 +3,6 @@ package cn.iocoder.yudao.module.iot.service.device.upstream; | ||
| 3 | import cn.hutool.core.util.IdUtil; | 3 | import cn.hutool.core.util.IdUtil; |
| 4 | import cn.hutool.core.util.StrUtil; | 4 | import cn.hutool.core.util.StrUtil; |
| 5 | import cn.iocoder.yudao.framework.common.util.object.BeanUtils; | 5 | import cn.iocoder.yudao.framework.common.util.object.BeanUtils; |
| 6 | -import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils; | ||
| 7 | import cn.iocoder.yudao.module.iot.api.device.dto.IotDeviceEventReportReqDTO; | 6 | import cn.iocoder.yudao.module.iot.api.device.dto.IotDeviceEventReportReqDTO; |
| 8 | import cn.iocoder.yudao.module.iot.api.device.dto.IotDevicePropertyReportReqDTO; | 7 | import cn.iocoder.yudao.module.iot.api.device.dto.IotDevicePropertyReportReqDTO; |
| 9 | import cn.iocoder.yudao.module.iot.api.device.dto.IotDeviceStatusUpdateReqDTO; | 8 | import cn.iocoder.yudao.module.iot.api.device.dto.IotDeviceStatusUpdateReqDTO; |
| @@ -47,7 +46,8 @@ public class IotDeviceUpstreamServiceImpl implements IotDeviceUpstreamService { | @@ -47,7 +46,8 @@ public class IotDeviceUpstreamServiceImpl implements IotDeviceUpstreamService { | ||
| 47 | public void reportDevicePropertyData(IotDevicePropertyReportReqDTO reportReqDTO) { | 46 | public void reportDevicePropertyData(IotDevicePropertyReportReqDTO reportReqDTO) { |
| 48 | // 1.1 获得设备 | 47 | // 1.1 获得设备 |
| 49 | log.info("[reportDevicePropertyData][上报设备属性数据: {}]", reportReqDTO); | 48 | log.info("[reportDevicePropertyData][上报设备属性数据: {}]", reportReqDTO); |
| 50 | - IotDeviceDO device = getDevice(reportReqDTO); | 49 | + IotDeviceDO device = deviceService.getDeviceByProductKeyAndDeviceNameFromCache( |
| 50 | + reportReqDTO.getProductKey(), reportReqDTO.getDeviceName()); | ||
| 51 | if (device == null) { | 51 | if (device == null) { |
| 52 | log.error("[reportDevicePropertyData][设备({}/{})不存在]", | 52 | log.error("[reportDevicePropertyData][设备({}/{})不存在]", |
| 53 | reportReqDTO.getProductKey(), reportReqDTO.getDeviceName()); | 53 | reportReqDTO.getProductKey(), reportReqDTO.getDeviceName()); |
| @@ -71,11 +71,6 @@ public class IotDeviceUpstreamServiceImpl implements IotDeviceUpstreamService { | @@ -71,11 +71,6 @@ public class IotDeviceUpstreamServiceImpl implements IotDeviceUpstreamService { | ||
| 71 | // TODO 芋艿:待实现 | 71 | // TODO 芋艿:待实现 |
| 72 | } | 72 | } |
| 73 | 73 | ||
| 74 | - private IotDeviceDO getDevice(IotDeviceUpstreamAbstractReqDTO reqDTO) { | ||
| 75 | - return TenantUtils.executeIgnore(() -> // 需要忽略租户,因为请求时,未带租户编号 | ||
| 76 | - deviceService.getDeviceByProductKeyAndDeviceName(reqDTO.getProductKey(), reqDTO.getDeviceName())); | ||
| 77 | - } | ||
| 78 | - | ||
| 79 | private void updateDeviceLastTime(IotDeviceDO deviceDO, IotDeviceUpstreamAbstractReqDTO reqDTO) { | 74 | private void updateDeviceLastTime(IotDeviceDO deviceDO, IotDeviceUpstreamAbstractReqDTO reqDTO) { |
| 80 | // TODO 芋艿:插件状态 | 75 | // TODO 芋艿:插件状态 |
| 81 | // TODO 芋艿:操作时间 | 76 | // TODO 芋艿:操作时间 |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thingmodel/IotThingModelService.java
| @@ -46,7 +46,6 @@ public interface IotThingModelService { | @@ -46,7 +46,6 @@ public interface IotThingModelService { | ||
| 46 | */ | 46 | */ |
| 47 | IotThingModelDO getThingModel(Long id); | 47 | IotThingModelDO getThingModel(Long id); |
| 48 | 48 | ||
| 49 | - // TODO @芋艿:增加缓存 | ||
| 50 | /** | 49 | /** |
| 51 | * 获得产品物模型列表 | 50 | * 获得产品物模型列表 |
| 52 | * | 51 | * |
| @@ -56,20 +55,22 @@ public interface IotThingModelService { | @@ -56,20 +55,22 @@ public interface IotThingModelService { | ||
| 56 | List<IotThingModelDO> getThingModelListByProductId(Long productId); | 55 | List<IotThingModelDO> getThingModelListByProductId(Long productId); |
| 57 | 56 | ||
| 58 | /** | 57 | /** |
| 59 | - * 获得产品物模型分页 | 58 | + * 【缓存】获得产品物模型列表 |
| 60 | * | 59 | * |
| 61 | - * @param pageReqVO 分页查询 | ||
| 62 | - * @return 产品物模型分页 | 60 | + * 注意:该方法会忽略租户信息,所以调用时,需要确认会不会有跨租户访问的风险!!! |
| 61 | + * | ||
| 62 | + * @param productKey 产品标识 | ||
| 63 | + * @return 产品物模型列表 | ||
| 63 | */ | 64 | */ |
| 64 | - PageResult<IotThingModelDO> getProductThingModelPage(IotThingModelPageReqVO pageReqVO); | 65 | + List<IotThingModelDO> getThingModelListByProductKeyFromCache(String productKey); |
| 65 | 66 | ||
| 66 | /** | 67 | /** |
| 67 | - * 获得产品物模型列表 | 68 | + * 获得产品物模型分页 |
| 68 | * | 69 | * |
| 69 | - * @param productKey 产品 Key | ||
| 70 | - * @return 产品物模型列表 | 70 | + * @param pageReqVO 分页查询 |
| 71 | + * @return 产品物模型分页 | ||
| 71 | */ | 72 | */ |
| 72 | - List<IotThingModelDO> getProductThingModelListByProductKey(String productKey); | 73 | + PageResult<IotThingModelDO> getProductThingModelPage(IotThingModelPageReqVO pageReqVO); |
| 73 | 74 | ||
| 74 | /** | 75 | /** |
| 75 | * 获得产品物模型列表 | 76 | * 获得产品物模型列表 |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thingmodel/IotThingModelServiceImpl.java
| @@ -2,8 +2,11 @@ package cn.iocoder.yudao.module.iot.service.thingmodel; | @@ -2,8 +2,11 @@ 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.extra.spring.SpringUtil; | ||
| 5 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 6 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 6 | import cn.iocoder.yudao.framework.common.util.object.BeanUtils; | 7 | import cn.iocoder.yudao.framework.common.util.object.BeanUtils; |
| 8 | +import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore; | ||
| 9 | +import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils; | ||
| 7 | import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.model.ThingModelEvent; | 10 | import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.model.ThingModelEvent; |
| 8 | import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.model.ThingModelParam; | 11 | import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.model.ThingModelParam; |
| 9 | import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.model.ThingModelService; | 12 | import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.model.ThingModelService; |
| @@ -14,11 +17,14 @@ import cn.iocoder.yudao.module.iot.convert.thingmodel.IotThingModelConvert; | @@ -14,11 +17,14 @@ import cn.iocoder.yudao.module.iot.convert.thingmodel.IotThingModelConvert; | ||
| 14 | import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO; | 17 | import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO; |
| 15 | import cn.iocoder.yudao.module.iot.dal.dataobject.thingmodel.IotThingModelDO; | 18 | import cn.iocoder.yudao.module.iot.dal.dataobject.thingmodel.IotThingModelDO; |
| 16 | import cn.iocoder.yudao.module.iot.dal.mysql.thingmodel.IotThingModelMapper; | 19 | import cn.iocoder.yudao.module.iot.dal.mysql.thingmodel.IotThingModelMapper; |
| 20 | +import cn.iocoder.yudao.module.iot.dal.redis.RedisKeyConstants; | ||
| 17 | import cn.iocoder.yudao.module.iot.enums.product.IotProductStatusEnum; | 21 | import cn.iocoder.yudao.module.iot.enums.product.IotProductStatusEnum; |
| 18 | import cn.iocoder.yudao.module.iot.enums.thingmodel.*; | 22 | import cn.iocoder.yudao.module.iot.enums.thingmodel.*; |
| 19 | import cn.iocoder.yudao.module.iot.service.product.IotProductService; | 23 | import cn.iocoder.yudao.module.iot.service.product.IotProductService; |
| 20 | import jakarta.annotation.Resource; | 24 | import jakarta.annotation.Resource; |
| 21 | import lombok.extern.slf4j.Slf4j; | 25 | import lombok.extern.slf4j.Slf4j; |
| 26 | +import org.springframework.cache.annotation.CacheEvict; | ||
| 27 | +import org.springframework.cache.annotation.Cacheable; | ||
| 22 | import org.springframework.stereotype.Service; | 28 | import org.springframework.stereotype.Service; |
| 23 | import org.springframework.transaction.annotation.Transactional; | 29 | import org.springframework.transaction.annotation.Transactional; |
| 24 | import org.springframework.validation.annotation.Validated; | 30 | import org.springframework.validation.annotation.Validated; |
| @@ -69,6 +75,9 @@ public class IotThingModelServiceImpl implements IotThingModelService { | @@ -69,6 +75,9 @@ public class IotThingModelServiceImpl implements IotThingModelService { | ||
| 69 | createDefaultEventsAndServices(createReqVO.getProductId(), createReqVO.getProductKey()); | 75 | createDefaultEventsAndServices(createReqVO.getProductId(), createReqVO.getProductKey()); |
| 70 | } | 76 | } |
| 71 | // TODO @puhui999: 服务和事件的情况 method 怎么设置?在前端设置还是后端设置? | 77 | // TODO @puhui999: 服务和事件的情况 method 怎么设置?在前端设置还是后端设置? |
| 78 | + | ||
| 79 | + // 7. 删除缓存 | ||
| 80 | + deleteThingModelListCache(createReqVO.getProductKey()); | ||
| 72 | return thingModel.getId(); | 81 | return thingModel.getId(); |
| 73 | } | 82 | } |
| 74 | 83 | ||
| @@ -92,6 +101,9 @@ public class IotThingModelServiceImpl implements IotThingModelService { | @@ -92,6 +101,9 @@ public class IotThingModelServiceImpl implements IotThingModelService { | ||
| 92 | if (Objects.equals(updateReqVO.getType(), IotThingModelTypeEnum.PROPERTY.getType())) { | 101 | if (Objects.equals(updateReqVO.getType(), IotThingModelTypeEnum.PROPERTY.getType())) { |
| 93 | createDefaultEventsAndServices(updateReqVO.getProductId(), updateReqVO.getProductKey()); | 102 | createDefaultEventsAndServices(updateReqVO.getProductId(), updateReqVO.getProductKey()); |
| 94 | } | 103 | } |
| 104 | + | ||
| 105 | + // 6. 删除缓存 | ||
| 106 | + deleteThingModelListCache(updateReqVO.getProductKey()); | ||
| 95 | } | 107 | } |
| 96 | 108 | ||
| 97 | @Override | 109 | @Override |
| @@ -113,6 +125,9 @@ public class IotThingModelServiceImpl implements IotThingModelService { | @@ -113,6 +125,9 @@ public class IotThingModelServiceImpl implements IotThingModelService { | ||
| 113 | if (Objects.equals(thingModel.getType(), IotThingModelTypeEnum.PROPERTY.getType())) { | 125 | if (Objects.equals(thingModel.getType(), IotThingModelTypeEnum.PROPERTY.getType())) { |
| 114 | createDefaultEventsAndServices(thingModel.getProductId(), thingModel.getProductKey()); | 126 | createDefaultEventsAndServices(thingModel.getProductId(), thingModel.getProductKey()); |
| 115 | } | 127 | } |
| 128 | + | ||
| 129 | + // 4. 删除缓存 | ||
| 130 | + deleteThingModelListCache(thingModel.getProductKey()); | ||
| 116 | } | 131 | } |
| 117 | 132 | ||
| 118 | @Override | 133 | @Override |
| @@ -126,13 +141,15 @@ public class IotThingModelServiceImpl implements IotThingModelService { | @@ -126,13 +141,15 @@ public class IotThingModelServiceImpl implements IotThingModelService { | ||
| 126 | } | 141 | } |
| 127 | 142 | ||
| 128 | @Override | 143 | @Override |
| 129 | - public PageResult<IotThingModelDO> getProductThingModelPage(IotThingModelPageReqVO pageReqVO) { | ||
| 130 | - return thingModelMapper.selectPage(pageReqVO); | 144 | + @TenantIgnore |
| 145 | + @Cacheable(value = RedisKeyConstants.THING_MODEL_LIST, key = "#productKey") | ||
| 146 | + public List<IotThingModelDO> getThingModelListByProductKeyFromCache(String productKey) { | ||
| 147 | + return thingModelMapper.selectListByProductKey(productKey); | ||
| 131 | } | 148 | } |
| 132 | 149 | ||
| 133 | @Override | 150 | @Override |
| 134 | - public List<IotThingModelDO> getProductThingModelListByProductKey(String productKey) { | ||
| 135 | - return thingModelMapper.selectListByProductKey(productKey); | 151 | + public PageResult<IotThingModelDO> getProductThingModelPage(IotThingModelPageReqVO pageReqVO) { |
| 152 | + return thingModelMapper.selectPage(pageReqVO); | ||
| 136 | } | 153 | } |
| 137 | 154 | ||
| 138 | @Override | 155 | @Override |
| @@ -333,4 +350,16 @@ public class IotThingModelServiceImpl implements IotThingModelService { | @@ -333,4 +350,16 @@ public class IotThingModelServiceImpl implements IotThingModelService { | ||
| 333 | .setDirection(direction.getDirection())); | 350 | .setDirection(direction.getDirection())); |
| 334 | } | 351 | } |
| 335 | 352 | ||
| 353 | + private void deleteThingModelListCache(String productKey) { | ||
| 354 | + // 保证在 @CacheEvict 之前,忽略租户 | ||
| 355 | + TenantUtils.executeIgnore(() -> getSelf().deleteThingModelListCache0(productKey)); | ||
| 356 | + } | ||
| 357 | + | ||
| 358 | + @CacheEvict(value = RedisKeyConstants.THING_MODEL_LIST, key = "#productKey") | ||
| 359 | + public void deleteThingModelListCache0(String productKey) {} | ||
| 360 | + | ||
| 361 | + private IotThingModelServiceImpl getSelf() { | ||
| 362 | + return SpringUtil.getBean(getClass()); | ||
| 363 | + } | ||
| 364 | + | ||
| 336 | } | 365 | } |