Commit a364153d4a9a34375151d8527a5ad54ed60f6c22

Authored by YunaiV
1 parent 7745035f

【功能优化】IoT:device 和 thingmodel 读取增加缓存

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&lt;IotThingModelDO&gt; { @@ -68,8 +72,4 @@ public interface IotThingModelMapper extends BaseMapperX&lt;IotThingModelDO&gt; {
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 }