SpringCache -- Redis --- 配置与缓存使用--配置过期时间

2023-09-18 17:41:15
写在前面:
学redis,还是得搭配SpringCache来玩一玩。
前置内容

导入依赖

        <!--redis依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <!--redis连接池 -->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-pool2</artifactId>
        </dependency>
        <!--SpringCache缓存 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-cache</artifactId>
        </dependency>

配置cache

在yml下

spring:
	cache:
		type: redis
		redis:
			key-prefix: Client_ #key前缀,如果配置了cacheManager则失效
     		use-key-prefix: true #是否开启key前缀
      		cache-null-values: true #是否缓存空值

在配置类上加上@EnableCaching开启缓存
配置序列化器
RedisConfig implements CachingConfigurer
redis的序列化器配置见前文,

    /**
     * 对缓存进行序列化和反序列化的配置
     * @param factory redis连接工厂
     * @return
     */
    @Bean
    public CacheManager cacheManager(RedisConnectionFactory factory){
        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
                .entryTtl(Duration.ofDays(1)) // 配置缓存时长
                // 注意0为永久用于 Duration.ZERO 声明永久缓存。
                .prefixCacheNameWith("Client:") // 前缀
                .computePrefixWith(cacheName -> "caching:" + cacheName); //前缀动态
                .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(RedisSerializer.string())) // key序列化方式
                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(RedisSerializer.json())); // value序列化方式
        return RedisCacheManager.builder(factory)
                .cacheDefaults(config)
                .build();
    }

使用

在这里配置就差不多了,在需要进行缓存操作的地方加注解就可以了

@Cacheable

该注解为缓存获取注解:

如果缓存中没有则进行查询在添加到缓存,如果缓存有则直接走缓存

属性

  • value/cacheName
    他们互为别名
    确定目标高速缓存(或高速缓存),与特定 Bean 定义的限定符值或 Bean 名匹配
    最终缓存的key为prefix+cacheName:: key
  • key
    指定缓存的key,可以使用Spring Expression Language (SpEL) 表达式来进行动态设置。

SpEL 表达式:

  1. 可以使用 #root.method, #root.target, and #root.caches 来指定 方法, 目标对象和受影响的缓存的method引用
    @cacheable(value =“phone”,key="#root.methodName”)
    指定方法名来作为
  2. 可以使用#形参名字来使用,下面是用phone的id来
    @Cacheable(value = “Phone”,key=“#phone.id”)
    public Result<List> getAll(Phone phone)
  3. 方法参数可以通过索引访问。例如,可以通过 或 #p1 #a1访问#root.args[1]第二个参数。如果该信息可用,也可以按名称访问参数。
  • cacheManager
    指定管理器
  • condition
    缓存的条件,可以为空,使用SPEL表达式编写,返回true或者false,true表示存入缓存
  • KeyGenerator
    指定key生成对策
    如果是自定义对象类型,判断不了可以自定义KeyGenerator
@Component
public class MyGenerator implements KeyGenerator{
	@override
	public Object generate(object o, Method method, object... objects){
 		
	}
}
  • unless
    用于否决缓存放置操作的 Spring 表达式语言 (SpEL) 表达式。如果条件的计算结果为 true。
    默认值为 “”,表示缓存永远不会被否决。
  • cacheResolver
    要使用的自定义 org.springframework.cache.interceptor.CacheResolver 的 Bean 名称。

@CachePut

更新缓存
每次都会调用方法,把返回值缓存起来,每次都会更新/新增
注解和前面一样

@CacheEvict

删除缓存
调用后删除指定缓存
注解相同,多了几个

  • allEntries
    是否删除缓存中的所有条目。
  • beforeInvocation
    是否应在调用该方法之前进行逐出。
    将此属性设置为 true,会导致逐出发生,而不考虑方法结果(即,是否引发异常)。

配置过期时间

我是2种方法都配置了的

依据cacheName设置

主要在与对于每一个cacheName设置不同的RedisCacheConfiguration
多个cacheName就加多个withCacheConfiguration就可以了

    /**
     * 对缓存进行序列化和反序列化的配置
     *
     * @param factory redis连接工厂
     * @return
     */
    @Bean
    public CacheManager cacheManager(RedisTemplate<String, Object> redisTemplate, RedisConnectionFactory factory) {
        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
                .entryTtl(Duration.ofDays(1)) // 配置缓存时长
                .prefixCacheNameWith("Client:") // 前缀
                .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(RedisSerializer.string())) // key序列化方式
                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(RedisSerializer.json())); // value序列化方式
                // 如果不需要第二种就把CustomRedisCacheManager换成RedisCacheManager
        return CustomRedisCacheManager.RedisCacheManagerBuilder
                .fromConnectionFactory(factory)
                .cacheDefaults(config)
                .withCacheConfiguration("contact:relation", getCacheConfigurationWithTtl(redisTemplate, Duration.ofMinutes(30)))
                .transactionAware()
                .build();
    }
    RedisCacheConfiguration getCacheConfigurationWithTtl(RedisTemplate<String, Object> template, Duration time) {
        return RedisCacheConfiguration
                .defaultCacheConfig()
                .prefixCacheNameWith("Client:") // 前缀
                // 设置key为String
                .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(template.getStringSerializer()))
                // 设置value 为自动转Json的Object
                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(template.getValueSerializer()))
                // 不缓存null
                .disableCachingNullValues()
                // 缓存数据保存1小时
                .entryTtl(time);
    }

在注解上截取过期时间

在cacheName上面加上#时间就可以了


/**
 * 自定义缓存管理器
 */
public class CustomRedisCacheManager extends RedisCacheManager {

    public CustomRedisCacheManager(RedisCacheWriter cacheWriter, RedisCacheConfiguration defaultCacheConfiguration) {
        super(cacheWriter, defaultCacheConfiguration);
    }

    /**
     * 针对@Cacheable设置缓存过期时间
     * @param name
     * @param cacheConfig
     * @return
     */
    @Override
    protected RedisCache createRedisCache(String name, RedisCacheConfiguration cacheConfig) {
        String[] array = StringUtils.delimitedListToStringArray(name, "#");
        // 解析TTL
        if (array.length > 2) {
            char c = array[1].charAt(array.length - 1);
            long ttl = Long.parseLong(StrUtil.sub(array[1], 0, array[1].length() - 1));
            cacheConfig = switch (c){
                case 's','S' -> cacheConfig.entryTtl(Duration.ofSeconds(ttl));
                case 'm','M' -> cacheConfig.entryTtl(Duration.ofMinutes(ttl));
                case 'h','H' -> cacheConfig.entryTtl(Duration.ofHours(ttl));
                case 'd','D' -> cacheConfig.entryTtl(Duration.ofDays(ttl));
                default -> cacheConfig.entryTtl(Duration.ofSeconds(Long.parseLong(array[1])));
            }
            cacheConfig = cacheConfig.entryTtl(Duration.ofSeconds(ttl)); // 注意单位我此处用的是秒,而非毫秒
        }
        return super.createRedisCache(array[0], cacheConfig);
    }

}
更多推荐

【RocketMQ专题】快速实战及集群架构原理详解

目录课程内容一、MQ简介基本介绍*作用(解决什么问题)二、RocketMQ产品特点2.1RocketMQ介绍2.2RocketMQ特点2.3RocketMQ的运行架构2.4消息模型三、RocketMQ快速实战3.1快速搭建RocketMQ服务3.2快速实现消息收发3.3搭建Maven客户端项目3.4搭建RocketMQ

计算机专业毕业设计项目推荐07-科研成果管理系统(JavaSpringBoot+Vue+Mysql)

科研成果管理系统(JavaSpringBoot+Vue+Mysql)**介绍****系统总体开发情况-功能模块****各部分模块实现****最后想说的****联系方式**介绍本系列(后期可能博主会统一为专栏)博文献给即将毕业的计算机专业同学们,因为博主自身本科和硕士也是科班出生,所以也比较了解计算机专业的毕业设计流程以

浅谈终端安全接入

前言:随着网络的发展,现代企业大多都会部署企业的有线网络与无线网络,在传统的企业网内,随着越来越多的终端设备接入到公司网络,管理人员控制和审计外部用户接入的企业办公网的难度和工作量也越来越大。而如果允许外部用户随意使用企业网络,则可能在管理人员和系统维护人员毫不知情的情况下,某些恶意用户侵入企业办公网络,从而造成数据泄

瑞芯微 RV1126 芯片的完整启动流程

瑞芯微RV1126启动流程瑞芯微RV1126芯片的启动流程,包括MiniLoaderAll.bin、U-Boot、内核(Kernel)和根文件系统(RootFileSystem)的加载和执行过程。1.上电复位当设备上电或复位时,RV1126芯片进入初始状态。2.BootROM运行BootROM是硬件逻辑中的引导程序,它

本地Docker Registry远程连接,为你带来高效便捷的镜像管理体验!

Linux本地DockerRegistry本地镜像仓库远程连接文章目录Linux本地DockerRegistry本地镜像仓库远程连接1.部署DockerRegistry2.本地测试推送镜像3.Linux安装cpolar4.配置DockerRegistry公网访问地址5.公网远程推送DockerRegistry6.固定D

CESM地球系统模式教程

详情点击公众号技术科研吧链接:CESM地球系统模式教程前言目前通用地球系统模式(CommunityEarthSystemModel,CESM)在研究地球的过去、现在和未来的气候状况中具有越来越普遍的应用。CESM由美国NCAR于2010年07月推出以来,一直受到气候学界的密切关注。近年升级的CESM2.0在大气、陆地、

ElasticSearch系列-简介与安装详解

全文检索讲ElasticSearch之前,需要先提一下全文检索.全文检索是计算机程序通过扫描文章中的每一个词,对每一个词建立一个索引,指明该词在文章中出现的次数和位置。当用户查询时根据建立的索引查找,类似于通过字典的检索字表查字的过程。索引:建立索引文本---->切分--->词文章出现过出现多少次检索:查询关键词---

基于TensorFlow+CNN+协同过滤算法的智能电影推荐系统——深度学习算法应用(含微信小程序、ipynb工程源码)+MovieLens数据集(三)

目录前言总体设计系统整体结构图系统流程图运行环境模块实现1.模型训练1)数据集分析2)数据预处理3)模型创建(1)定义参数(2)定义网络数据输入占位符(3)定义用户嵌入矩阵(4)定义电影嵌入矩阵(5)定义电影类型嵌入矩阵(6)处理电影名称(7)全连接层(8)定义计算图相关其它博客工程源代码下载其它资料下载前言本项目专注

MySQL事务

MySQL事务一、事务的概念二、事务的ACID特点1、原子性2、一致性3、隔离性3.1、事务的隔离级别3.1.1测试脏读3.1.2测试提交读3.1.3测试可重复读3.2、查询全局事务隔离级别3.3、查询会话事务隔离级别3.4、设置全局事务隔离级别3.5、设置会话事务隔离级别4、持久性三、事务控制语句1、测试提交事务2、

SQL如何从数据库中查找数据是否存在

SQL查找是否存在,别再用count!!!问题背景在业务开发中,经常遇到如下需求:从数据库中查找符合一组条件的数据是否存在。结果也无非两种状态:“有”或者“没有”。模拟数据表CREATETABLE`user`(`id`bigintNOTNULLCOMMENT'id',`userName`varchar(256)CHAR

springboot集成canal实现同步双写

一.canal服务端canal是阿里巴巴MySQL数据库Binlog的增量订阅&消费组件。基于数据库增量日志解析,提供增量数据订阅&消费。二.基于docker搭建在docker环境中1.执行dockersearchcanal获取到需要下载的canal镜像2.执行dockerpull选择下载的canal镜像3.执行run

热文推荐