当前位置: 首页 > 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++覆盖和重载的区别
  • php的引用
  • [译]前端离线指南(上)
  • “大数据应用场景”之隔壁老王(连载四)
  • Apache的基本使用
  • centos安装java运行环境jdk+tomcat
  • CSS盒模型深入
  • gulp 教程
  • Javascript基础之Array数组API
  • java第三方包学习之lombok
  • js作用域和this的理解
  • python3 使用 asyncio 代替线程
  • React Transition Group -- Transition 组件
  • Redis学习笔记 - pipline(流水线、管道)
  • Spring思维导图,让Spring不再难懂(mvc篇)
  • SwizzleMethod 黑魔法
  • tweak 支持第三方库
  • 不发不行!Netty集成文字图片聊天室外加TCP/IP软硬件通信
  • 分类模型——Logistics Regression
  • 今年的LC3大会没了?
  • 聊一聊前端的监控
  • 容器化应用: 在阿里云搭建多节点 Openshift 集群
  • 使用 @font-face
  • 双管齐下,VMware的容器新战略
  • 消息队列系列二(IOT中消息队列的应用)
  • 小程序01:wepy框架整合iview webapp UI
  • 一个JAVA程序员成长之路分享
  • 用mpvue开发微信小程序
  • #pragma 指令
  • (C#)Windows Shell 外壳编程系列9 - QueryInfo 扩展提示
  • (四)c52学习之旅-流水LED灯
  • (四)JPA - JQPL 实现增删改查
  • (转)Android中使用ormlite实现持久化(一)--HelloOrmLite
  • .chm格式文件如何阅读
  • .NET HttpWebRequest、WebClient、HttpClient
  • .NET教程 - 字符串 编码 正则表达式(String Encoding Regular Express)
  • .NET下的多线程编程—1-线程机制概述
  • .net与java建立WebService再互相调用
  • .NET中的Exception处理(C#)
  • /proc/interrupts 和 /proc/stat 查看中断的情况
  • [ CTF ]【天格】战队WriteUp- 2022年第三届“网鼎杯”网络安全大赛(青龙组)