当前位置: 首页 > news >正文

Google的guava缓存学习使用

导入依赖

<dependency><groupId>com.google.guava</groupId><artifactId>guava</artifactId><version>31.1-jre</version>
</dependency>

使用

项目中使用到了缓存,定义一个切面,拦截类或方法上存在@SysDataCache注解请求,对于这些方法的返回值进行缓存。项目中主要还是使用在缓存常量,一些不易改变的值

定义注解

@Documented
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface SysDataCache {}

定义切面和初始化缓存容器并使用缓存

@Aspect   //定义一个切面
@Configuration
public class SysDataCacheAspect {private static Logger logger = LogManager.getLogger(SysDataCacheAspect.class);private static final  Map<String,Boolean> cacheFileNames = new ConcurrentHashMap<String, Boolean>();private static LoadingCache<String,Object> cache = null;static {// CacheLoader 初始化CacheLoader<String, Object> cacheLoader = new CacheLoader<String, Object>() {@Override// load方法的作用是在通过get方法从LoadingCache获取不到值时去加载该值并放入缓存。public Object load(String key) throws Exception {return null;}};cache = CacheBuilder.newBuilder()// 设置容量大小.maximumSize(80000)//默认一天后过期.expireAfterWrite(10, TimeUnit.DAYS).removalListener(new RemovalListener<String, Object>() {@Overridepublic void onRemoval(RemovalNotification<String, Object> notification) {if(notification.getValue()!=null && notification.getValue() instanceof CacheFile) {CacheFile cacheFile = (CacheFile)notification.getValue();removeCacheFile(cacheFile.fileName);}}})// 加载器配置.build(cacheLoader);}private String normalizedArgsStr(Object[] args){if(args==null || args.length==0) {return "";}Object[] normalizedArgs = new Object[args.length];if(args!=null) {for(int i=0;i<args.length;i++) {Object arg = args[i];if(arg instanceof AccessTokenUser) {AccessTokenUser user = (AccessTokenUser)arg;normalizedArgs[i]= user.getUserId();}else {normalizedArgs[i]=arg;}}}return JsonConverter.toJsonStr(normalizedArgs);}@Around("execution(* (@com.xysd.bizbase.annotation.SysDataCache *).*(..)) || execution(@com.xysd.bizbase.annotation.SysDataCache * *(..))")public Object process(ProceedingJoinPoint point) throws Throwable {String className = point.getSignature().getDeclaringTypeName();String methodName = point.getSignature().getName();Object[] args = point.getArgs();String key = className+"_$_"+methodName+"_$_"+(normalizedArgsStr(args));Object cached = cache.getIfPresent(key);if(methodName.endsWith("_dontCache")){return point.proceed(args);}if(cached!=null) {if(cached instanceof CacheFile) {CacheFile cachedFile = (CacheFile)cached;Object cachedData =  readCachedData(cachedFile);if(cachedData==null) {//读取缓存失败return point.proceed(args);}else {return cachedData;}}else {return cached;}}else {cached = point.proceed(args);if(cached instanceof ApiResultDTO){if(((ApiResultDTO<?>) cached).getData() == null) return cached;}if(cached!=null) {try {CacheFile cachedFile = cacheToDiskIfNecessary(cached);if(cachedFile!=null) {cache.put(key, cachedFile);}else {cache.put(key, cached);}}catch(Exception e) {logger.error("缓存失败,失败信息{}",e.getMessage());e.printStackTrace();}}return cached;}}private Object readCachedData(CacheFile cachedFile) {String fileName = cachedFile.getFileName();String absolutePath = getAbsoluteCacheFilePath(fileName);File f = new File(absolutePath);InputStream in = null;ObjectInputStream oin = null;try {in = new FileInputStream(f);oin = new ObjectInputStream(in);Object cachedData = oin.readObject();return cachedData;}catch(Exception e) {logger.error("读取缓存序列化文件失败,失败信息:{}",e.getMessage());e.printStackTrace();return null;}finally {Utils.clean(in,oin);}}/*** 当value序列化后占用字节大于50K时写入磁盘进行缓存* @param value* @return*/private CacheFile cacheToDiskIfNecessary(Object value) {int cachThreadshold = 50*1024;ByteArrayOutputStream bos = null ; ObjectOutputStream oos = null;try {bos = new ByteArrayOutputStream();oos = new ObjectOutputStream(bos);oos.writeObject(value);oos.flush();byte[] byteArray = bos.toByteArray();if(byteArray!=null && byteArray.length>cachThreadshold) {return buildCacheFile(byteArray);}else {return null;}}catch(Exception e) {throw new RuntimeException(e);}finally {Utils.clean(bos,oos);}}private CacheFile buildCacheFile(byte[] byteArray) {String fileName = "syscachefile_"+Utils.getUUID("");String absolutePath = getAbsoluteCacheFilePath(fileName);File f = new File(absolutePath);OutputStream out = null;try {if(!f.getParentFile().exists()) {f.getParentFile().mkdirs();}out = new FileOutputStream(f);out.write(byteArray);out.flush();cacheFileNames.put(fileName, true);return new CacheFile(fileName);}catch(Exception e) {throw new RuntimeException(e);}finally {Utils.clean(out);}}private static String getAbsoluteCacheFilePath(String fileName) {String sysCacheBaseDir = Utils.getTmpDirRoot()+"/sysDataCache";return sysCacheBaseDir+"/"+fileName;}public static void removeCacheFile(String fileName) {if(StringUtils.isNoneBlank(fileName)) {cacheFileNames.remove(fileName);String absolutePath = getAbsoluteCacheFilePath(fileName);File f = new File(absolutePath);try {if(f.exists() && f.isFile()) {f.delete();}}catch(Exception e) {//删除失败不做任何处理e.printStackTrace();}}}/*** 清空缓存*/public static final void clearCache() {for(String fileName:cacheFileNames.keySet()) {removeCacheFile(fileName);}cacheFileNames.clear();cache.invalidateAll();}public static class CacheFile implements Serializable {private static final long serialVersionUID = -6926387004863371705L;private String fileName;public CacheFile(String fileName) {super();this.fileName = fileName;}public String getFileName() {return fileName;}}}

项目中缓存使用

@Service
@Transactional
@SuppressWarnings("unchecked")
public class SysDatasServiceImpl implements _ISysDatasService {private final static ConstantItem dataKey_dict_politicalStatus = new ConstantItem("politicalStatus", "政治身份");@Override@SysDataCache@Transactional(readOnly = true)public Map<String, String> getSysDataKeysInfo(AccessTokenUser user) {result.put((String) dataKey_dict_politicalStatus.getId(), dataKey_dict_politicalStatus.getName());}@Override@SysDataCache@Transactional(readOnly = true)public Map<String, Object> getSysDatasByDataKeys(AccessTokenUser user, Map<String, Object> dataKeyAndParams) {if (dataKey_dict_politicalStatus.getId().equals(entry.getKey())) {//政治身份Map<String, Object> dictParams = (Map<String, Object>) entry.getValue();data.put(entry.getKey(), getDictValue(entry.getKey(), dictParams));continue;}}//从字典中获取数据private List<SimpTreeNode> getDictValue(String dictCodes, Map<String, Object> params) {if("all".equals(dictCodes)){List<SysDataSimpleDTO> rootDicts = systemGatewayService.findAllRootDicts(1);dictCodes = Optional.ofNullable(rootDicts).orElse(new ArrayList<>()).stream().map(r->r.getId().replace("-","")).collect(Collectors.joining(","));}else if (params != null && params.get("dictCodes") != null) {dictCodes = (String) params.get("dictCodes");params.remove("dictCodes");}List<SimpTreeNode> codeList = systemGatewayService.findDictSimTreeNodeByDictCodes(dictCodes, params);return codeList;}
}

相关文章:

  • vue创建组件和使用
  • 去除 inline-block 元素间间距的方法
  • c语言不定参数
  • html+css+javascript实现贪吃蛇游戏
  • C++高级编程——STL:list容器、set容器和map容器
  • Pytest基础
  • [pytorch入门] 6. 神经网络
  • 小程序样例3:根据日历创建待办事项
  • 数灵通丨可以实现抖音引流微信小程序了
  • 腾讯云短信开发
  • css中>>>、/deep/、::v-deep的作用和区别,element-ui自定义样式
  • Docker搭建私有仓库
  • java spring cloud 企业工程管理系统源码+二次开发+定制化服务
  • 【单例模式】保证线程安全实现单例模式
  • 决策树(Python)
  • android百种动画侧滑库、步骤视图、TextView效果、社交、搜房、K线图等源码
  • crontab执行失败的多种原因
  • ES学习笔记(10)--ES6中的函数和数组补漏
  • hadoop集群管理系统搭建规划说明
  • iBatis和MyBatis在使用ResultMap对应关系时的区别
  • Linux后台研发超实用命令总结
  • nginx 负载服务器优化
  • Otto开发初探——微服务依赖管理新利器
  • Redis在Web项目中的应用与实践
  • 程序员该如何有效的找工作?
  • 高度不固定时垂直居中
  • 关于 Linux 进程的 UID、EUID、GID 和 EGID
  • 记一次用 NodeJs 实现模拟登录的思路
  • 来,膜拜下android roadmap,强大的执行力
  • 聊一聊前端的监控
  • 前端每日实战:70# 视频演示如何用纯 CSS 创作一只徘徊的果冻怪兽
  • 如何学习JavaEE,项目又该如何做?
  • 数据库写操作弃用“SELECT ... FOR UPDATE”解决方案
  • 一份游戏开发学习路线
  • 原生JS动态加载JS、CSS文件及代码脚本
  • 再谈express与koa的对比
  • postgresql行列转换函数
  • 函数计算新功能-----支持C#函数
  • ​ubuntu下安装kvm虚拟机
  • ​一、什么是射频识别?二、射频识别系统组成及工作原理三、射频识别系统分类四、RFID与物联网​
  • # 达梦数据库知识点
  • #define,static,const,三种常量的区别
  • #LLM入门|Prompt#1.8_聊天机器人_Chatbot
  • #控制台大学课堂点名问题_课堂随机点名
  • #微信小程序:微信小程序常见的配置传旨
  • (1)常见O(n^2)排序算法解析
  • (day 12)JavaScript学习笔记(数组3)
  • (Matlab)基于蝙蝠算法实现电力系统经济调度
  • (多级缓存)多级缓存
  • (附源码)springboot 校园学生兼职系统 毕业设计 742122
  • (附源码)计算机毕业设计ssm基于Internet快递柜管理系统
  • (论文阅读11/100)Fast R-CNN
  • (论文阅读23/100)Hierarchical Convolutional Features for Visual Tracking
  • (欧拉)openEuler系统添加网卡文件配置流程、(欧拉)openEuler系统手动配置ipv6地址流程、(欧拉)openEuler系统网络管理说明
  • (学习日记)2024.01.09