在现系统中使用了一个字典表,更新或插入字典表需要做Redis缓存
@Override @Cache(name = Constants.REDIS_PREFIX_DIC, desc = "变更字典后更新") public int editDict(DictEntity data) { int editCnt = -1; Date d = new Date(); Integer dictId = data.getDictId(); data.setUpdatedDate(d); if (dictId != null && dictId > 0) { editCnt = dictDao.updatedByPrimaryKeySelective(data); } else { data.setCreatedDate(d); data.setCreatedBy(data.getUpdatedBy()); editCnt = dictDao.insertSelective(data); dictId = data.getDictId(); } dictItemsDao.deleteByDictId(dictId); List<DictItemsEntity> list = new ArrayList<DictItemsEntity>(); for (DictItemsEntity item : data.getItemsList()) { item.setDictId(dictId); list.add(item); } dictItemsDao.insertByList(list); return editCnt; }
在此之上使用了一个@Catch的注解,这个注解是自己重写的,做Redis缓存的更新操作
@Catch注解:
package com.jn.baseservice.annotation; import com.jn.baseservice.common.RedisConstant; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.METHOD}) public @interface Cache { /** * 缓存名 * * @return */ String name(); /** * 更新范围 * * @return */ String range() default RedisConstant.RANGE_WHOLE; /** * 描述 * * @return */ String desc() default ""; }
其中以下两个注解可以去:https://www.cnblogs.com/peida/archive/2013/04/24/3036689.html 中查看
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
之后使用一个切面,用于监听Redis更改缓存的操作:
package com.jn.ssr.superrescue.config; import com.jn.baseservice.annotation.Cache; import com.jn.baseservice.common.RedisConstant; import com.jn.ssr.superrescue.cache.CacheFactory; import com.jn.ssr.superrescue.cache.DictCache; import com.jn.ssr.superrescue.tools.SpringConfigTool; import lombok.extern.log4j.Log4j2; import org.aspectj.lang.annotation.*; import org.springframework.stereotype.Component; import org.springframework.util.StopWatch; @Aspect @Component @Log4j2 /** * 用于监听更改缓存的操作 */ public class CacheAspect { //切面范围:com.hhh.test.super下的service.impl 下所有的public开头的方法 @Pointcut("execution(public * com.hhh.test.super.*.*.service.impl..*.*(..))") public void cacheCut() { } //这个就是以上Redis的Catch的实现 @AfterReturning(returning = "ret", pointcut = "cacheCut()", value = "@annotation(cache)") public void doAfterReturning(Object ret, Cache cache) throws Throwable { log.info("欢迎更改缓存:{}", ret); StopWatch watch = new StopWatch(); watch.start(cache.name()); CacheFactory factory = (CacheFactory) SpringConfigTool.getBean(DictCache.factoryMap.get(cache.name())); boolean result = cache.range().equals(RedisConstant.RANGE_WHOLE) ? factory.create().wholeRefresh() : factory.create().simpleRefresh(cache.name()); watch.stop(); log.info("缓存更新结果 {} taskName:{},耗时:{}ms,描述:{}", result, watch.getLastTaskName(), watch.getLastTaskTimeMillis(), cache.desc()); } }
调用了catchFactory:其中有一个create方法,返回一个CatcherUpdate对象:
package com.jn.ssr.superrescue.cache; public interface CacheFactory { CacheUpdate create(); }
CatchUpdate中提供两个方法:
package com.jn.ssr.superrescue.cache; public interface CacheUpdate { /** * vue调用组件 */ String key = "key"; String label = "label"; String id = "id"; String parentId = "parentId"; default boolean simpleRefresh(String name) { return true; } boolean wholeRefresh(); }
这个类的实现类是:
package com.jn.ssr.superrescue.cache.impl; import com.jn.baseservice.common.Constants; import com.jn.baseservice.common.RedisConstant; import com.jn.baseservice.entity.dict.DictEntity; import com.jn.baseservice.entity.dict.DictItemsEntity; import com.jn.baseservice.utils.DateUtils; import com.jn.baseservice.utils.RedisHandle; import com.jn.ssr.superrescue.cache.CacheUpdate; import connector.dict.DictService; import lombok.extern.log4j.Log4j2; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import java.util.*; import java.util.concurrent.ConcurrentHashMap; /** * 字典类缓存 * */ @Component @Log4j2 public class DicCache implements CacheUpdate { @Autowired private RedisHandle redisHandle; @Autowired private DictService dictService; @Override public boolean simpleRefresh(String dicCode) { boolean result = true; try { DictEntity search = new DictEntity(); search.setDictCode(dicCode); commonAdd(search); } catch (Exception e) { result = false; log.error("字典部分更新失败:", e); } return result; } @Override public boolean wholeRefresh() { boolean result = true; try { commonAdd(new DictEntity()); } catch (Exception e) { result = false; log.error("字典全量更新失败:", e); } return result; } /** * 抽离公共部分 * * @param search */ private void commonAdd(DictEntity search) { search = new DictEntity();//需要全量更新 到REDIS_PREFIX_WEB_DIC log.info("添加基础数据字典"); long start = System.currentTimeMillis(); List<DictEntity> list = dictService.findBatchItems(search); Map<String, List<Map<String, String>>> dictMaps = new ConcurrentHashMap<>(); for (DictEntity tmp : list) { String code = tmp.getDictCode(); if (tmp.getCompanyId() != null && tmp.getCompanyId() > 0) { code += "_" + tmp.getCompanyId(); } List<Map<String, String>> dictItems = new ArrayList<Map<String, String>>(); List<DictItemsEntity> itemsList = tmp.getItemsList(); Map<String, String> itemsMap = new LinkedHashMap<String, String>(); for (DictItemsEntity item : itemsList) { Map<String, String> webMap = new LinkedHashMap<String, String>(); webMap.put("key", item.getDictKey()); webMap.put("label", item.getDictValue()); webMap.put("id", item.getDictItemId().toString()); webMap.put("parentId", item.getDictItemId().toString()); dictItems.add(webMap); itemsMap.put(item.getDictKey(), item.getDictValue()); } redisHandle.set(Constants.REDIS_PREFIX_DIC + code, itemsMap); redisHandle.set(Constants.REDIS_PREFIX_WEB_DIC + code, dictItems); dictMaps.put(code, dictItems); } redisHandle.set(Constants.REDIS_PREFIX_WEB_DIC, dictMaps); Date d = new Date(); //更新本号 String version = DateUtils.formatDate(d, "yyyyMMddHHmmss"); redisHandle.hset(RedisConstant.DIC_CACHE_VERSION_TABLE, RedisConstant.DIC_DICT_VERSION, version); log.info("更新数据字典版本为:{}", version); log.info("添加基础数据字典 结束 共计{}秒", (System.currentTimeMillis() - start) / 1000.0); } }
sy_dict与sp_dict——items表:
CREATE TABLE `sy_dict` ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主码', `dict_code` varchar(32) NOT NULL DEFAULT '' COMMENT '标识', `company_id` int(11) DEFAULT '0' COMMENT '归属公司(0公用)', `is_disabled` tinyint(4) DEFAULT '1' COMMENT '是否可删除编辑 0 不可删除编辑,1可删除编辑', `description` varchar(100) DEFAULT '' COMMENT '字典描述', `created_date` datetime DEFAULT NULL COMMENT '创建时间', `created_by` int(11) DEFAULT NULL COMMENT '创建者', `updated_date` datetime DEFAULT NULL COMMENT '更新人', `updated_by` int(11) DEFAULT NULL COMMENT '更改人', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=213 DEFAULT CHARSET=utf8 COMMENT='数据字典表'; CREATE TABLE `sy_dict_items` ( `dict_item_id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主码', `dict_id` int(11) NOT NULL COMMENT '字典id', `dict_key` varchar(32) DEFAULT '' COMMENT '键', `dict_value` varchar(100) DEFAULT '' COMMENT '值', `priority` int(11) DEFAULT '0' COMMENT '优先级', `parent_id` int(11) DEFAULT NULL COMMENT '父子项目id', PRIMARY KEY (`dict_item_id`), KEY `fk_dictitem_dictid` (`dict_id`), CONSTRAINT `sy_dict_items_ibfk_1` FOREIGN KEY (`dict_id`) REFERENCES `sy_dict` (`id`) ON DELETE CASCADE ) ENGINE=InnoDB AUTO_INCREMENT=1509 DEFAULT CHARSET=utf8 COMMENT='数据字典表';