微服务想缓存一些数据,不希望重复调用。java SoftReference软引用存储缓存
背景:微服务我们要调用字典数据,但是很多都是要重复调用的,没有缓存,我为了设置一个应用的缓存,并且可以 定时清理,更新
首先定义两个静态数据,。一个软连接缓存,一个定时清理线程
private static SoftReference<Map<String, Map<String, DictionaryVo>>> plmDicMapCache = new SoftReference<>(new ConcurrentHashMap<>()); static ScheduledExecutorService executorService = new ScheduledThreadPoolExecutor(1, new BasicThreadFactory.Builder().namingPattern("example-schedule-pool-%d").daemon(true).build());
定时清理逻辑,一分钟清理一次,时间可以自己设置
static { executorService.scheduleAtFixedRate(() -> { if (plmDicMapCache.get() != null) { Map<String, Map<String, DictionaryVo>> stringMapMap = plmDicMapCache.get(); if (stringMapMap != null) { stringMapMap.clear(); log.info("-----------定时清理字典表缓存 plmDicMapCache-----"); } else { plmDicMapCache = new SoftReference<>(new ConcurrentHashMap<>()); } } else { plmDicMapCache = new SoftReference<>(new ConcurrentHashMap<>()); } }, 1, 1, TimeUnit.MINUTES); }
调用方法,以及赋值
public static <T> void convertDicNamePlm(SFunction<T, ?> funcSource, SFunction<T, ?> funcTarget, String groupIdentification, T objects) { Map<String, Map<String, DictionaryVo>> plmDicList; Map<String, Map<String, DictionaryVo>> stringMapMap = plmDicMapCache.get(); if (stringMapMap == null) { plmDicMapCache = new SoftReference<>(new ConcurrentHashMap<>()); stringMapMap = new ConcurrentHashMap<>(); } if (!stringMapMap.containsKey(groupIdentification)) {
//远程调用的数据方法 plmDicList = getPlmDicList(groupIdentification); stringMapMap.putAll(plmDicList); log.info("字典没缓存了======---- {}", groupIdentification); } else { Map<String, DictionaryVo> stringDictionaryVoMap = stringMapMap.get(groupIdentification); plmDicList = new HashMap<>(); plmDicList.put(groupIdentification, stringDictionaryVoMap); log.info("字典走缓存 {}", groupIdentification); }
String fieldNameSource = getFieldName(funcSource); Object fieldValueSource = ReflectUtil.getFieldValue(objects, fieldNameSource); Map<String, DictionaryVo> stringDictionaryVoMap = plmDicList.get(groupIdentification); DictionaryVo dictionaryVo = stringDictionaryVoMap.get(fieldValueSource + ""); String fieldNameTarget = getFieldName(funcTarget); ReflectUtil.setFieldValue(objects, fieldNameTarget, dictionaryVo.getName()); }
这段是根据lamda function 获取数据字段名称,反射赋值
String fieldNameSource = getFieldName(funcSource); Object fieldValueSource = ReflectUtil.getFieldValue(objects, fieldNameSource); Map<String, DictionaryVo> stringDictionaryVoMap = plmDicList.get(groupIdentification); DictionaryVo dictionaryVo = stringDictionaryVoMap.get(fieldValueSource + ""); String fieldNameTarget = getFieldName(funcTarget); ReflectUtil.setFieldValue(objects, fieldNameTarget, dictionaryVo.getName());
public static <T> void convertDicNamePlm(SFunction<T, ?> funcSource, SFunction<T, ?> funcTarget, String groupIdentification, T objects, Map<String, Map<String, DictionaryVo>> plmDicList) {
String fieldNameSource = getFieldName(funcSource);
Object fieldValueSource = ReflectUtil.getFieldValue(objects, fieldNameSource);
Map<String, DictionaryVo> stringDictionaryVoMap = plmDicList.get(groupIdentification);
DictionaryVo dictionaryVo = stringDictionaryVoMap.get(fieldValueSource + "");
String fieldNameTarget = getFieldName(funcTarget);
ReflectUtil.setFieldValue(objects, fieldNameTarget, dictionaryVo.getName());
}
public static <T> String getFieldName(SFunction<T, ?> func) {
SerializedLambda resolve = LambdaUtils.resolve(func);
String method = resolve.getImplMethodName();
return BeanUtil.getFieldName(method);
}
如何调用呢?拿分页举例:
DictionaryUtil.convertDicNamePlm(DingdingApprovalClassVo::getApproveClass,DingdingApprovalClassVo::getApproveClassName,"dingding_approve_class",record);
public PageResult<DingdingApprovalClassVo> page(PageParameter<DingdingApprovalClassVo> parameter) { Page<DingdingApprovalClassVo> queryPage = PageUtil.getPage(parameter, true); Page<DingdingApprovalClassVo> resultPageList = dingdingApprovalClassMapper.queryListPage(queryPage, parameter.getSelectParameter());
for (DingdingApprovalClassVo record : resultPageList.getRecords()) {
//这里是赋值 DictionaryUtil.convertDicNamePlm(DingdingApprovalClassVo::getApproveClass,DingdingApprovalClassVo::getApproveClassName, "dingding_approve_class",record); } return new PageResult<>(resultPageList); }
完整代码
import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.util.ReflectUtil; import com.alibaba.fastjson.JSON; import com.baomidou.mybatisplus.core.toolkit.LambdaUtils; import com.baomidou.mybatisplus.core.toolkit.support.SFunction; import com.baomidou.mybatisplus.core.toolkit.support.SerializedLambda; import com.orderplus.core.enumeration.ReturnCode; import com.orderplus.core.feign.BambooService; import com.orderplus.core.feign.PublicService; import com.orderplus.core.handle.BusinessException; import com.orderplus.core.vo.pdm.DictionaryVo; import com.orderplus.core.vo.publicService.CommonVo; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.concurrent.BasicThreadFactory; import java.lang.ref.SoftReference; import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.TimeUnit; import java.util.function.Function; import java.util.stream.Collectors; @Slf4j public class DictionaryUtil { private static SoftReference<Map<String, Map<String, DictionaryVo>>> plmDicMapCache = new SoftReference<>(new ConcurrentHashMap<>()); static ScheduledExecutorService executorService = new ScheduledThreadPoolExecutor(1, new BasicThreadFactory.Builder().namingPattern("example-schedule-pool-%d").daemon(true).build()); static { executorService.scheduleAtFixedRate(() -> { if (plmDicMapCache.get() != null) { Map<String, Map<String, DictionaryVo>> stringMapMap = plmDicMapCache.get(); if (stringMapMap != null) { stringMapMap.clear(); log.info("-----------定时清理字典表缓存 plmDicMapCache-----"); } else { plmDicMapCache = new SoftReference<>(new ConcurrentHashMap<>()); } } else { plmDicMapCache = new SoftReference<>(new ConcurrentHashMap<>()); } }, 1, 1, TimeUnit.MINUTES); }public static Map<String, Map<String, DictionaryVo>> getPlmDicList(String... groupIdentification) { BambooService bean = ApplicationContextProvider.getBean(BambooService.class); Result<List<DictionaryVo>> resp = bean.queryCommonDictionaryByGroups(Arrays.asList(groupIdentification)); log.info("BambooService.queryBaseDictionary resp:{}", JSON.toJSONString(resp)); if (resp == null) { throw new BusinessException(ReturnCode.PUBLIC_CALL_ERR); } if (!ReturnCode.success.getCode().equals(resp.getCode())) { throw new BusinessException(resp.getCode(), resp.getMsg(), null); } List<DictionaryVo> data = resp.getData(); if (CollectionUtil.isEmpty(data)) { return new HashMap<>(); } Map<String, List<DictionaryVo>> dicMap = data.stream().collect(Collectors.groupingBy(DictionaryVo::getGroupIdentification)); Map<String, Map<String, DictionaryVo>> dicMapGroup = new LinkedHashMap<>(); dicMap.forEach((k, v) -> { Map<String, DictionaryVo> map = v.stream().collect(Collectors.toMap(DictionaryVo::getValue, Function.identity(), (v1, v2) -> v1)); dicMapGroup.put(k, map); }); return dicMapGroup; } public static <T> void convertDicNamePlm(SFunction<T, ?> funcSource, SFunction<T, ?> funcTarget, String groupIdentification, T objects) { Map<String, Map<String, DictionaryVo>> plmDicList; Map<String, Map<String, DictionaryVo>> stringMapMap = plmDicMapCache.get(); if (stringMapMap == null) { plmDicMapCache = new SoftReference<>(new ConcurrentHashMap<>()); stringMapMap = new ConcurrentHashMap<>(); } if (!stringMapMap.containsKey(groupIdentification)) { plmDicList = getPlmDicList(groupIdentification); stringMapMap.putAll(plmDicList); log.info("字典没缓存了======---- {}", groupIdentification); } else { Map<String, DictionaryVo> stringDictionaryVoMap = stringMapMap.get(groupIdentification); plmDicList = new HashMap<>(); plmDicList.put(groupIdentification, stringDictionaryVoMap); log.info("字典走缓存 {}", groupIdentification); } String fieldNameSource = getFieldName(funcSource); Object fieldValueSource = ReflectUtil.getFieldValue(objects, fieldNameSource); Map<String, DictionaryVo> stringDictionaryVoMap = plmDicList.get(groupIdentification); DictionaryVo dictionaryVo = stringDictionaryVoMap.get(fieldValueSource + ""); String fieldNameTarget = getFieldName(funcTarget); ReflectUtil.setFieldValue(objects, fieldNameTarget, dictionaryVo.getName()); } public static <T> void convertDicNamePlm(SFunction<T, ?> funcSource, SFunction<T, ?> funcTarget, String groupIdentification, T objects, Map<String, Map<String, DictionaryVo>> plmDicList) { String fieldNameSource = getFieldName(funcSource); Object fieldValueSource = ReflectUtil.getFieldValue(objects, fieldNameSource); Map<String, DictionaryVo> stringDictionaryVoMap = plmDicList.get(groupIdentification); DictionaryVo dictionaryVo = stringDictionaryVoMap.get(fieldValueSource + ""); String fieldNameTarget = getFieldName(funcTarget); ReflectUtil.setFieldValue(objects, fieldNameTarget, dictionaryVo.getName()); } public static <T> String getFieldName(SFunction<T, ?> func) { SerializedLambda resolve = LambdaUtils.resolve(func); String method = resolve.getImplMethodName(); return BeanUtil.getFieldName(method); } }