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

@cacheable 是否缓存成功_让我们来学习学习SpringCache分布式缓存,为什么用?

Spring Cache

简介

  • Cache接口为缓存的组件规范定义,包含缓存的各种操作集合
  • Cache接口下Spring提供了各种xxcache的实现;如RedisCache,EhCacheCache,ConcurrentMapCache等;
  • 每次调用需要缓存功能的方法时,Spring会检查检查指定参数的指定的目标方法是否已经被调用过;如果有就直接从缓存中获取方法调用后的结果,如果没有就调用方法并缓存结果后返回给用户。下次调用直接从缓存中获取。

63847739e88085d1f14ca5b853f53cd4.png

引入依赖

<!--引入spring cache-->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-cache</artifactId>
		</dependency>

配置

spring.cache.type=redis

开启注解

@EnableCaching

常用注解

  • @Cacheable:触发操作将数据保存到缓存中,参数value指cacheName
  • @CacheEvict:触发操作将数据从缓存中删除(运用于失效模式)
  • @CachePut:不影响方法执行更新(运用于双写模式)
  • @Caching:组合以上多个操作
  • @CacheConfig:再类级别上共享有关缓存的配置

默认配置

  • key自动生成:缓存名字::SimpleKey[]
  • value默认是jdk序列化
  • 默认ttl时间:-1
  • 默认查询数据如果缓存中存在,则不再调用方法,直接将缓存中命中的数据返回

自定义配置

d0e0b27d9a7365530d8035b2ea0d9c7c.png
  • 指定key:
    • key默认为spel表达式:#root.method.name指用方法名作为key保存在缓存中
      • @Cacheable(value="category",key="#root.methodName")

3f5d5a2dba0352eb7b2708204897faf7.png
    • key是字符串的话额外要加单引号(默认会做表达式解析)
      • @Cacheable(value=“category”,key=“‘catalogJson-cache’”)
    • 缓存key表达为:
      • 指定前缀(前提:有指定前缀并且开启了使用前缀)+指定key名

fd18b4c4f6cf6f50b945e3e41c33e9ef.png
      • 推荐: 默认前缀(缓存名字,前提:允许使用前缀,没有指定前缀):: key名字 (并且保存在以指定的缓存名字namespace下,树形结构显示)

a1abe67adc6c7f7c9722dc6e3c78f84e.png
      • key名字(前提:无前缀)

62ac115847c63a42318a1bc7f61c700f.png
  • 指定其他信息
    spring.cache.type=redis #指定ttl,单位必需(m,s,h,d) spring.cache.redis.time-to-live=3600000m spring.cache.redis.key-prefix=CACHE_ spring.cache.redis.use-key-prefix=true #默认允许缓存空值->解决缓存穿透问题,暂时性保存null给其他并发线程返回,以保护数据库 spring.cache.redis.cache-null-values=true
  • 将value改为json格式(默认Jdk序列化器)
    Redis序列化器:

9a7ff7cf94831bf136b82374d1d8eeae.png
@EnableCaching
@Configuration
public class MyCacheConfig {

    @Bean
    RedisCacheConfiguration cacheConfiguration(CacheProperties cacheProperties){
        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig();
        //entryTtl方法返回一个新的RedisCacheConfiguration对象覆盖原有对象,其他属性方法也是如此
        //cacheConfig=cacheConfig.entryTtl()
        //config = config.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()));
        config = config.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()));

        //整合配置文件(不整合配置文件所配置的内容不生效)
        //取出配置信息
        CacheProperties.Redis redisProperties = cacheProperties.getRedis();

        if (redisProperties.getTimeToLive() != null) {
            config = config.entryTtl(redisProperties.getTimeToLive());
        }

        if (redisProperties.getKeyPrefix() != null) {
            config = config.prefixKeysWith(redisProperties.getKeyPrefix());
        }

        if (!redisProperties.isCacheNullValues()) {
            config = config.disableCachingNullValues();
        }

        if (!redisProperties.isUseKeyPrefix()) {
            config = config.disableKeyPrefix();
        }

        return config;
    }

}

更新缓存数据

1、@CacheEvict

用于缓存失效模式:修改后删除该缓存信息

@CacheEvict 是用来标注在需要清除缓存元素的方法或类上的

  • 单个删除:
    在方法上标注(一般为保存,更新方法)@CacheEvict(value="category",key="'getLevel1Categories'")
    表示一旦执行该方法则会从缓存中删除对应的key
  • 批量删除:
  1. @Caching批量操作
    @Caching(evict = { @CacheEvict(value="category",key="'getLevel1Categories'"), @CacheEvict(value="category",key="'getCatalogJson'") })
  2. 删除整个namespace(一般统一类型的数据存放在同一个分区中)@CacheEvict(value="category",allEntries = true)
  • allEntries:默认为false,当其为true时表示清除缓存中的所有元素
  • beforeInvocation:默认是false,表示执行方法后删除(当方法如果因为抛出异常而未能成功返回时也不会触发清除操作),当指定该属性值为true时,Spring会在调用该方法之前清除缓存中的指定元素。

2、@CachePut

用于缓存双写模式:修改后立即写入缓存

@CachePut标注的方法在执行前不会去检查缓存中是否存在之前执行过的结果,而是每次都会执行方法,并将结果(方法返回值)存入指定的缓存中

造个轮子

我们经常说不要重复造轮子。为了开发效率,可以不造轮子,但是必须具备造轮子的能力。建议造一个简单的MQ,你能用到通信协议、设计模式、队列等许多知识。在造轮子的过程中,你会频繁的翻阅各种手册或者博客,这就是用输出倒逼输入。

dd22b9e1c4a59076bf6d6974114d8221.png

上面是我自己整理的一些学习资料,还有一些大公司面试题,比较干货,需要的朋友可以私信我回复‘资料’,或者点下方文档我可以免费分享。

石墨文档​shimo.im

相关文章:

  • zookeeper集群_Docker实战之Zookeeper集群
  • kibana 查看有多少索引库_kibana-1:使用timeline构建时间序列图
  • cordova打开外部链接_AutoCAD小秘密050:外部参照面面观(上)
  • asp.net通过webservice调用java接口全过程_springboot整合Feign实现远程接口调用
  • 检测到目标url存在框架注入漏洞_CVE201914234:Django JSONField SQL注入漏洞复现
  • 随机森林的特征 是放回抽样么_机器学习军火库 | 浪漫算法 随机森林
  • java空字符_Java学习之路008天
  • py怎么运行_Mac Tensorflow Faster R-CNN CPU实现环境配置及Demo运行
  • 一个数等于两个不同素数的乘机_【朝夕的ACM笔记】数论-反素数
  • spring是什么_Spring 源码第三弹!EntityResolver 是个什么鬼?
  • python界面开发webview_Python使用Pyqt5实现简易浏览器!非常实用!
  • 程序实例python_Python花式编程案例集锦(5)
  • python装饰器作用和功能_Python装饰器实现类Java注解功能
  • 树莓派无屏幕安装kali_树莓派制作魔镜屏幕旋转不正确的处理方法
  • 没有与参数列表匹配的重载函数_C++覆盖和重载的区别
  • angular2开源库收集
  • docker python 配置
  • express.js的介绍及使用
  • Linux链接文件
  • MySQL数据库运维之数据恢复
  • Python实现BT种子转化为磁力链接【实战】
  • React系列之 Redux 架构模式
  • SpiderData 2019年2月16日 DApp数据排行榜
  • Vue.js-Day01
  • 二维平面内的碰撞检测【一】
  • 深入浅出webpack学习(1)--核心概念
  • 时间复杂度与空间复杂度分析
  • 译自由幺半群
  • 原创:新手布局福音!微信小程序使用flex的一些基础样式属性(一)
  • 【云吞铺子】性能抖动剖析(二)
  • ionic入门之数据绑定显示-1
  • ​一些不规范的GTID使用场景
  • # 数论-逆元
  • #NOIP 2014# day.1 生活大爆炸版 石头剪刀布
  • (10)工业界推荐系统-小红书推荐场景及内部实践【排序模型的特征】
  • (12)目标检测_SSD基于pytorch搭建代码
  • (2024,RWKV-5/6,RNN,矩阵值注意力状态,数据依赖线性插值,LoRA,多语言分词器)Eagle 和 Finch
  • (C语言)共用体union的用法举例
  • (delphi11最新学习资料) Object Pascal 学习笔记---第7章第3节(封装和窗体)
  • (Redis使用系列) Springboot 使用redis的List数据结构实现简单的排队功能场景 九
  • (附源码)springboot 基于HTML5的个人网页的网站设计与实现 毕业设计 031623
  • (五)c52学习之旅-静态数码管
  • (转)菜鸟学数据库(三)——存储过程
  • (转)创业的注意事项
  • (转)原始图像数据和PDF中的图像数据
  • .net framework4与其client profile版本的区别
  • .NET的微型Web框架 Nancy
  • .net反编译工具
  • .NET开源全面方便的第三方登录组件集合 - MrHuo.OAuth
  • .NET委托:一个关于C#的睡前故事
  • @FeignClient注解,fallback和fallbackFactory
  • [ 渗透测试面试篇 ] 渗透测试面试题大集合(详解)(十)RCE (远程代码/命令执行漏洞)相关面试题
  • []指针
  • [Asp.net MVC]Asp.net MVC5系列——Razor语法
  • [BUUCTF NewStarCTF 2023 公开赛道] week3 crypto/pwn