From 88c2ea407545d92ac5d419c5f14cff936398305f Mon Sep 17 00:00:00 2001 From: mh Date: Fri, 8 Nov 2024 17:31:14 +0800 Subject: [PATCH] =?UTF-8?q?1=E3=80=81=E6=B3=A8=E8=A7=A3=E9=85=8D=E7=BD=AE?= =?UTF-8?q?=E5=AD=97=E5=85=B8=E8=BD=AC=E6=8D=A2=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/mh/user/annotation/FieldParam.java | 48 +++++++ .../mh/user/annotation/TranslationDict.java | 17 +++ .../mh/user/aspect/DictDataTranslateAsp.java | 136 ++++++++++++++++++ .../mh/user/config/CaffeineCacheConfig.java | 62 ++++++++ .../java/com/mh/user/constants/Constant.java | 1 + .../controller/DevicesManageController.java | 15 +- .../controller/MeterManageController.java | 7 + .../com/mh/user/job/CollectionLoopRunner.java | 11 ++ .../com/mh/user/service/SysDictService.java | 2 + .../user/service/impl/SysDictServiceImpl.java | 19 ++- .../user/strategy/ModbusProtocolStrategy.java | 4 +- 11 files changed, 313 insertions(+), 9 deletions(-) create mode 100644 user-service/src/main/java/com/mh/user/annotation/FieldParam.java create mode 100644 user-service/src/main/java/com/mh/user/annotation/TranslationDict.java create mode 100644 user-service/src/main/java/com/mh/user/aspect/DictDataTranslateAsp.java create mode 100644 user-service/src/main/java/com/mh/user/config/CaffeineCacheConfig.java diff --git a/user-service/src/main/java/com/mh/user/annotation/FieldParam.java b/user-service/src/main/java/com/mh/user/annotation/FieldParam.java new file mode 100644 index 0000000..d7eca0c --- /dev/null +++ b/user-service/src/main/java/com/mh/user/annotation/FieldParam.java @@ -0,0 +1,48 @@ +package com.mh.user.annotation; + +import java.lang.annotation.*; + +/** + * @author LJF + * @version 1.0 + * @project mh_esi + * @description 数据字典注解 + * @date 2024-11-08 11:40:46 + */ +@Target(ElementType.FIELD) +@Inherited +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface FieldParam { + + /** + * 字典值 + * @return + */ + String value() default ""; + + /** + * 字典类型 + * @return + */ + String type() default ""; + + /** + * 字典标签 + * @return + */ + String label() default ""; + + /** + * 要翻译的字段,目标字段翻译的字段+Str + * @return + */ + String targetField() default ""; + + /** + * 要翻译的字段值类型 + * @return + */ + Class targetFieldValueClazz() default String.class; + +} diff --git a/user-service/src/main/java/com/mh/user/annotation/TranslationDict.java b/user-service/src/main/java/com/mh/user/annotation/TranslationDict.java new file mode 100644 index 0000000..189a9df --- /dev/null +++ b/user-service/src/main/java/com/mh/user/annotation/TranslationDict.java @@ -0,0 +1,17 @@ +package com.mh.user.annotation; + +import java.lang.annotation.*; + +/** + * @author LJF + * @version 1.0 + * @project mh_esi + * @description 需要翻译的字典值 + * @date 2024-11-08 14:29:39 + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.METHOD) +@Documented +public @interface TranslationDict { + FieldParam[] value(); +} diff --git a/user-service/src/main/java/com/mh/user/aspect/DictDataTranslateAsp.java b/user-service/src/main/java/com/mh/user/aspect/DictDataTranslateAsp.java new file mode 100644 index 0000000..fe51199 --- /dev/null +++ b/user-service/src/main/java/com/mh/user/aspect/DictDataTranslateAsp.java @@ -0,0 +1,136 @@ +package com.mh.user.aspect; + +import com.alibaba.fastjson2.JSONObject; +import com.baomidou.mybatisplus.core.toolkit.StringUtils; +import com.mh.user.annotation.FieldParam; +import com.mh.user.annotation.TranslationDict; +import com.mh.user.model.SysDict; +import com.mh.user.service.SysDictService; +import lombok.extern.slf4j.Slf4j; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.reflect.MethodSignature; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.lang.reflect.Method; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * @author LJF + * @version 1.0 + * @project mh_esi + * @description 数据字典转换 + * @date 2024-11-08 14:08:20 + */ +@Aspect +@Component +@Slf4j +public class DictDataTranslateAsp { + + @Autowired + private SysDictService sysDictService; + + @Around("@annotation(com.mh.user.annotation.TranslationDict)") + public Object aroundMethodTranslate(ProceedingJoinPoint joinPoint) throws Throwable { + // 接收到请求时间 + Long startTime = System.currentTimeMillis(); + // 注意,如果调用joinPoint.proceed()方法,则修改的参数值不会生效,必须调用joinPoint.proceed(args) + Object result = joinPoint.proceed(); + + // 获取返回值类型 + Class returnType = ((MethodSignature) joinPoint.getSignature()).getReturnType(); + + // 取出要翻译的字典值 + String returnJsonResult = JSONObject.toJSONString(result); + + // 开始解析 + Method method = ((MethodSignature) joinPoint.getSignature()).getMethod(); + + // 获取注解上参数 + TranslationDict annotation = method.getAnnotation(TranslationDict.class); + FieldParam[] fieldParams = annotation.value(); + + // 遍历 + for (FieldParam fieldParam : fieldParams) { + log.info("字典类型:{},取值字段:{}", fieldParam.type(), fieldParam.targetField()); + Pattern dictPattern = getPattern(fieldParam); + Matcher matcher = dictPattern.matcher(returnJsonResult); + StringBuffer sb = new StringBuffer(); + // 转义字段 + this.translateDict(fieldParam, dictPattern, matcher, sb); + matcher.appendTail(sb); + returnJsonResult = sb.toString(); + } + + result = JSONObject.parseObject(returnJsonResult, returnType); + // 如果这里不返回result,则目标对象实际返回值会被置为null + // 处理完成时间 + Long endTime = System.currentTimeMillis(); + log.info("数据字典转换耗时:{}ms", endTime - startTime); + return result; + } + + /** + * 字典值转义为中文 + * + * @param fieldParam + * @param fieldPattern + * @param fieldMatcher + * @param sb + */ + private void translateDict(FieldParam fieldParam, Pattern fieldPattern, Matcher fieldMatcher, StringBuffer sb) { + //从缓存中一次性取值 + List dictNames = sysDictService.findByType(fieldParam.type()); + while (fieldMatcher.find()) { + //取出要翻译字段对应的值 + Matcher dictValueMatcher = fieldPattern.matcher(fieldMatcher.group()); + dictValueMatcher.find(); + String group = dictValueMatcher.group(); + //""sex":1", ""sex":"1"",""sex":null" + //属性无值 + if (group.split(":").length <= 1) continue; + String dictName = ""; + //获取字典值 + String dictValue = group.split(":")[1].replace("\"", ""); + //属性值非为空 为空赋值空串 + if (StringUtils.isNotBlank(dictValue) && !dictValue.equalsIgnoreCase("null")) { + //多值 + if (dictValue.split(",").length > 1) { + for (String s : dictValue.split(",")) { + //fieldParam.dictType() + "_" + s 根据自己字典表设置的规则去查询 + String type = s; + Optional first = dictNames.stream().filter(d -> d.getValue().equals(type)).findFirst(); + if (!first.isPresent()) continue; + dictName += first.get().getLabel() + "/"; + } + } else { + String type = dictValue; + Optional first = dictNames.stream().filter(d -> d.getValue().equals(type)).findFirst(); + if (!first.isPresent()) continue; + dictName = first.get().getLabel(); + } + } + + String s = "\"" + fieldParam.targetField() + "Str" + "\":\"" + dictName + "\"," + fieldMatcher.group(); + log.info("拼接后字符串:{}", s); + fieldMatcher.appendReplacement(sb, s); + + } + } + + private Pattern getPattern(FieldParam fieldParam) { + Pattern fieldPattern;//属性整型 字符型 + if (fieldParam.targetFieldValueClazz().equals(Integer.class)) { + fieldPattern = Pattern.compile("\"" + fieldParam.targetField() + "\":(\\d+)?"); + } else { + fieldPattern = Pattern.compile("\"" + fieldParam.targetField() + "\":\"([0-9a-zA-Z_,]+)?\""); + } + return fieldPattern; + } +} diff --git a/user-service/src/main/java/com/mh/user/config/CaffeineCacheConfig.java b/user-service/src/main/java/com/mh/user/config/CaffeineCacheConfig.java new file mode 100644 index 0000000..00c59bd --- /dev/null +++ b/user-service/src/main/java/com/mh/user/config/CaffeineCacheConfig.java @@ -0,0 +1,62 @@ +package com.mh.user.config; + +import com.github.benmanes.caffeine.cache.*; +import lombok.extern.slf4j.Slf4j; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import java.util.concurrent.TimeUnit; + +/** + * @author LJF + * @title : + * @description 使用caffeine缓存技术 + * @updateTime 2020-12-15 + * @throws : + */ +@Slf4j +@Configuration +public class CaffeineCacheConfig { + + // 软引用: 如果一个对象只具有软引用,则内存空间足够,垃圾回收器就不会回收它;如果内存空间不足了,就会回收这些对象的内存。 + // 弱引用: 弱引用的对象拥有更短暂的生命周期。在垃圾回收器线程扫描它所管辖的内存区域的过程中,一旦发现了只具有弱引用的对象, + // 不管当前内存空间足够与否,都会回收它的内存 + @Bean(name = "caffeineCache") + public Cache caffeineCache() { + return Caffeine.newBuilder() + // 软引用 + .softValues() + // 弱引用 +// .weakValues() + // 设置最后一次写入或访问后经过固定时间过期 + .expireAfterWrite(8*60*60, TimeUnit.SECONDS) + // 初始的缓存空间大小 + .initialCapacity(100) + // 缓存的最大条数 + .maximumSize(1000) + .build(); + } + + //定义缓存,可直接使用 + @Bean + public LoadingCache expiryCache(){ + LoadingCache loadingCache = Caffeine.newBuilder() + .initialCapacity(100) + .maximumSize(1000) + //缓存写入/删除监控 + .writer(new CacheWriter() { + @Override + public void write(Object key, Object value) { //此方法是同步阻塞的 + log.info("--缓存写入--:key={}, value={}", key, value); + } + @Override + public void delete(Object key, Object value, RemovalCause cause) { + log.info("--缓存删除--:key={}", key); } + }) + .expireAfterAccess(6, TimeUnit.HOURS) //过期时间 + .build((String key)->"刷新的数据"); //cacheload实现类,刷新时候调用 +// loadingCache.put("name","侯征"); + return loadingCache; + } + +} diff --git a/user-service/src/main/java/com/mh/user/constants/Constant.java b/user-service/src/main/java/com/mh/user/constants/Constant.java index 65589e8..46c3c6a 100644 --- a/user-service/src/main/java/com/mh/user/constants/Constant.java +++ b/user-service/src/main/java/com/mh/user/constants/Constant.java @@ -11,6 +11,7 @@ public class Constant { public static final String FAIL = "fail"; public static final String SUCCESS = "success"; + public static final Object SYS_DICT = "sys_dict"; public static boolean CONTROL_WEB_FLAG = false; public static boolean SEND_STATUS = false; // 指令发送状态 public static boolean FLAG = false; diff --git a/user-service/src/main/java/com/mh/user/controller/DevicesManageController.java b/user-service/src/main/java/com/mh/user/controller/DevicesManageController.java index da88fed..d047ac4 100644 --- a/user-service/src/main/java/com/mh/user/controller/DevicesManageController.java +++ b/user-service/src/main/java/com/mh/user/controller/DevicesManageController.java @@ -3,7 +3,9 @@ package com.mh.user.controller; import com.mh.common.http.HttpResult; import com.mh.common.page.PageRequest; import com.mh.common.page.PageResult; +import com.mh.user.annotation.FieldParam; import com.mh.user.annotation.SysLogger; +import com.mh.user.annotation.TranslationDict; import com.mh.user.entity.DevicesManageEntity; import com.mh.user.service.DevicesManageService; import org.springframework.beans.factory.annotation.Autowired; @@ -23,38 +25,39 @@ public class DevicesManageController { @Autowired private DevicesManageService devicesManageService; - @SysLogger(value="资产管理信息",optDesc = "查询资产管理信息") + @SysLogger(value = "资产管理信息", optDesc = "查询资产管理信息") @PostMapping("/findByPage") + @TranslationDict({@FieldParam(type = "device_type", targetField = "deviceType", targetFieldValueClazz = Integer.class)}) public PageResult queryGatewayManage(@RequestBody PageRequest pageRequest) { return devicesManageService.queryByPage(pageRequest); } - @SysLogger(value="资产管理信息",optDesc = "编辑资产管理信息") + @SysLogger(value = "资产管理信息", optDesc = "编辑资产管理信息") @PostMapping("/update") public HttpResult updateProInfo(DevicesManageEntity entity) { devicesManageService.update(entity); return HttpResult.ok(); } - @SysLogger(value="资产管理信息",optDesc = "根据项目id查询对应信息") + @SysLogger(value = "资产管理信息", optDesc = "根据项目id查询对应信息") @GetMapping("/findById") public HttpResult findById(@RequestParam("id") Long id) { DevicesManageEntity entity = devicesManageService.findById(id); return HttpResult.ok(entity); } - @SysLogger(value="资产管理信息",optDesc = "添加资产管理信息") + @SysLogger(value = "资产管理信息", optDesc = "添加资产管理信息") @PostMapping("/save") public HttpResult saveDevice(DevicesManageEntity entity) { devicesManageService.save(entity); return HttpResult.ok(); } - @SysLogger(value="资产管理信息",optDesc = "删除资产管理信息") + @SysLogger(value = "资产管理信息", optDesc = "删除资产管理信息") @GetMapping("/deleteById") public HttpResult deleteProInfo(@RequestParam String id) { devicesManageService.delete(id); return HttpResult.ok(); } - + } diff --git a/user-service/src/main/java/com/mh/user/controller/MeterManageController.java b/user-service/src/main/java/com/mh/user/controller/MeterManageController.java index bcf5aeb..9f07915 100644 --- a/user-service/src/main/java/com/mh/user/controller/MeterManageController.java +++ b/user-service/src/main/java/com/mh/user/controller/MeterManageController.java @@ -3,7 +3,9 @@ package com.mh.user.controller; import com.mh.common.http.HttpResult; import com.mh.common.page.PageRequest; import com.mh.common.page.PageResult; +import com.mh.user.annotation.FieldParam; import com.mh.user.annotation.SysLogger; +import com.mh.user.annotation.TranslationDict; import com.mh.user.entity.MeterManageEntity; import com.mh.user.service.MeterManageService; import org.springframework.beans.factory.annotation.Autowired; @@ -23,6 +25,11 @@ public class MeterManageController { @Autowired private MeterManageService meterManageService; + @TranslationDict({@FieldParam(type = "device_type", targetField = "deviceType", targetFieldValueClazz = Integer.class), + @FieldParam(type = "communication_type", targetField = "communicationType", targetFieldValueClazz = Integer.class), + @FieldParam(type = "data_type", targetField = "dataType", targetFieldValueClazz = Integer.class), + @FieldParam(type = "protocol_type", targetField = "protocolType", targetFieldValueClazz = Integer.class), + }) @SysLogger(value="仪表管理信息",optDesc = "查询仪表管理信息") @PostMapping("/findByPage") public PageResult queryGatewayManage(@RequestBody PageRequest pageRequest) { diff --git a/user-service/src/main/java/com/mh/user/job/CollectionLoopRunner.java b/user-service/src/main/java/com/mh/user/job/CollectionLoopRunner.java index 734ada1..16976e1 100644 --- a/user-service/src/main/java/com/mh/user/job/CollectionLoopRunner.java +++ b/user-service/src/main/java/com/mh/user/job/CollectionLoopRunner.java @@ -46,6 +46,9 @@ public class CollectionLoopRunner implements ApplicationRunner { @Autowired private DeviceParamsService deviceParamsService; + @Autowired + private SysDictService sysDictService; + @Override public void run(ApplicationArguments args) throws Exception { List projectInfoEntities = projectInfoService.queryProjectInfo("1"); @@ -60,6 +63,14 @@ public class CollectionLoopRunner implements ApplicationRunner { } catch (Exception e) { log.info("6001端口已占用!"); } + + // 生成字典缓存 + createDictDataCache(); + } + + public void createDictDataCache() { + // 缓存字典值 + sysDictService.createDictDataCache(); } public void createOrderParamByStrategy(String systemId, String projectId) throws InterruptedException { diff --git a/user-service/src/main/java/com/mh/user/service/SysDictService.java b/user-service/src/main/java/com/mh/user/service/SysDictService.java index 248ba1a..7955424 100644 --- a/user-service/src/main/java/com/mh/user/service/SysDictService.java +++ b/user-service/src/main/java/com/mh/user/service/SysDictService.java @@ -25,4 +25,6 @@ public interface SysDictService extends CurdService { void updateByPrimaryKey(SysDict entity); List findByType(String type); + + void createDictDataCache(); } diff --git a/user-service/src/main/java/com/mh/user/service/impl/SysDictServiceImpl.java b/user-service/src/main/java/com/mh/user/service/impl/SysDictServiceImpl.java index 371d74e..cfcb4f5 100644 --- a/user-service/src/main/java/com/mh/user/service/impl/SysDictServiceImpl.java +++ b/user-service/src/main/java/com/mh/user/service/impl/SysDictServiceImpl.java @@ -1,18 +1,22 @@ package com.mh.user.service.impl; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.github.benmanes.caffeine.cache.Cache; import com.github.pagehelper.PageHelper; import com.github.pagehelper.PageInfo; import com.mh.common.page.MybatisPageHelper; import com.mh.common.page.PageRequest; import com.mh.common.page.PageResult; import com.mh.common.utils.StringUtils; -import com.mh.user.entity.MeterManageEntity; +import com.mh.user.constants.Constant; import com.mh.user.mapper.SysDictMapper; import com.mh.user.model.SysDict; import com.mh.user.service.SysDictService; import com.mh.user.utils.SecurityUtils; +import com.mh.user.utils.SpringBeanUtil; +import org.checkerframework.checker.units.qual.A; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Service; import java.util.Collections; @@ -32,6 +36,10 @@ public class SysDictServiceImpl implements SysDictService { @Autowired private SysDictMapper sysDictMapper; + @Autowired + @Qualifier("caffeineCache") + private Cache caffeineCache; + @Override public boolean deleteByPrimaryKey(Long id) { return sysDictMapper.deleteByPrimaryKey(id); @@ -89,4 +97,13 @@ public class SysDictServiceImpl implements SysDictService { public List findByType(String type) { return sysDictMapper.selectList(new QueryWrapper().eq("type", type)); } + + @Override + public void createDictDataCache() { + List sysDictList = sysDictMapper.selectList( + new QueryWrapper().orderByDesc("create_time")); + if (caffeineCache.getIfPresent(Constant.SYS_DICT) == null) { + caffeineCache.put("sys_dict", sysDictList); + } + } } diff --git a/user-service/src/main/java/com/mh/user/strategy/ModbusProtocolStrategy.java b/user-service/src/main/java/com/mh/user/strategy/ModbusProtocolStrategy.java index 59b6511..9a74247 100644 --- a/user-service/src/main/java/com/mh/user/strategy/ModbusProtocolStrategy.java +++ b/user-service/src/main/java/com/mh/user/strategy/ModbusProtocolStrategy.java @@ -186,7 +186,7 @@ public void initialDataResultCh(DeviceCodeParamEntity deviceCodeParam, DataResul //解析冷量表 public void analysisCloudOrder485(final String data, final DeviceCodeParamEntity deviceCodeParam) { - threadPoolService.execute(() -> { +// threadPoolService.execute(() -> { //创建SimpleDateFormat对象,指定样式 2019-05-13 22:39:30 Date date = new Date(); String dateStr = sdf1.format(date); @@ -241,7 +241,7 @@ public void analysisCloudOrder485(final String data, final DeviceCodeParamEntity } catch (Exception e) { log.error("保存冷量计数据失败!", e); } - }); +// }); } }