Redian新闻
>
Spring Cache 缓存注解这样用,实在是太香了!

Spring Cache 缓存注解这样用,实在是太香了!

公众号新闻

👉 这是一个或许对你有用的社群

🐱 一对一交流/面试小册/简历优化/求职解惑,欢迎加入芋道快速开发平台知识星球。下面是星球提供的部分资料: 

👉这是一个或许对你有用的开源项目

国产 Star 破 10w+ 的开源项目,前端包括管理后台 + 微信小程序,后端支持单体和微服务架构。

功能涵盖 RBAC 权限、SaaS 多租户、数据权限、商城、支付、工作流、大屏报表、微信公众号等等功能:

  • Boot 地址:https://gitee.com/zhijiantianya/ruoyi-vue-pro
  • Cloud 地址:https://gitee.com/zhijiantianya/yudao-cloud
  • 视频教程:https://doc.iocoder.cn

来源:waynblog


作者最近在开发公司项目时使用到 Redis 缓存,并在翻看前人代码时,看到了一种关于 @Cacheable 注解的自定义缓存有效期的解决方案,感觉比较实用,因此作者自己拓展完善了一番后分享给各位。

Spring 缓存常规配置

Spring Cache 框架给我们提供了 @Cacheable 注解用于缓存方法返回内容。但是 @Cacheable 注解不能定义缓存有效期。这样的话在一些需要自定义缓存有效期的场景就不太实用。

按照 Spring Cache 框架给我们提供的 RedisCacheManager 实现,只能在全局设置缓存有效期。这里给大家看一个常规的 CacheConfig 缓存配置类,代码如下,

@EnableCaching
@Configuration
public class CacheConfig extends CachingConfigurerSupport {
    ...

    private RedisSerializer<String> keySerializer() {
        return new StringRedisSerializer();
    }

    private RedisSerializer<Object> valueSerializer() {
        return new GenericFastJsonRedisSerializer();
    }

    public static final String CACHE_PREFIX = "crowd:";

    @Bean
    public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
        // 配置序列化(解决乱码的问题)
        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
                //设置key为String
                .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(keySerializer()))
                //设置value为自动转Json的Object
                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(valueSerializer()))
                .computePrefixWith(name -> CACHE_PREFIX + name  + ":")
                .entryTtl(Duration.ofSeconds(600));
        RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(Objects.requireNonNull(redisConnectionFactory));
        return new RedisCacheManager(redisCacheWriter, config);
    }
}

这里面简单对 RedisCacheConfiguration 缓存配置做一下说明:

  1. serializeKeysWith():设置 Redis 的 key 的序列化规则。
  2. erializeValuesWith():设置 Redis 的 value 的序列化规则。
  3. computePrefixWith():计算 Redis 的 key 前缀。
  4. entryTtl():全局设置 @Cacheable 注解缓存的有效期。

那么使用如上配置生成的 Redis 缓存 key 名称是什么样得嘞?这里用开源项目 crowd-adminConfigServiceImpl 类下 getValueByKey(String key) 方法举例,

@Cacheable(value = "configCache", key = "#root.methodName + '_' + #root.args[0]")
@Override
public String getValueByKey(String key) {
    QueryWrapper<Config> wrapper = new QueryWrapper<>();
    wrapper.eq("configKey", key);
    Config config = getOne(wrapper);
    if (config == null) {
        return null;
    }
    return config.getConfigValue();
}

执行此方法后,Redis 中缓存 key 名称如下,

crowd:configCache:getValueByKey_sys.name

TTL 过期时间是 287,跟我们全局设置的 300 秒基本是一致的。此时假如我们想把 getValueByKey 方法的缓存有效期单独设置为 600 秒,那我们该如何操作嘞?

@Cacheable 注解默认是没有提供有关缓存有效期设置的。想要单独修改 getValueByKey 方法的缓存有效期只能修改全局的缓存有效期。那么有没有别的方法能够为 getValueByKey 方法单独设置缓存有效期嘞?当然是有的,大家请往下看。

基于 Spring Boot + MyBatis Plus + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能

  • 项目地址:https://github.com/YunaiV/ruoyi-vue-pro
  • 视频教程:https://doc.iocoder.cn/video/

自定义 MyRedisCacheManager 缓存

其实我们可以通过自定义 MyRedisCacheManager 类继承 Spring Cache 提供的 RedisCacheManager 类后,重写 createRedisCache(String name, RedisCacheConfiguration cacheConfig) 方法,代码如下,

public class MyRedisCacheManager extends RedisCacheManager {
    public MyRedisCacheManager(RedisCacheWriter cacheWriter, RedisCacheConfiguration defaultCacheConfiguration) {
        super(cacheWriter, defaultCacheConfiguration);
    }

    @Override
    protected RedisCache createRedisCache(String name, RedisCacheConfiguration cacheConfig) {
        String[] array = StringUtils.split(name, "#");
        name = array[0];
         // 解析 @Cacheable 注解的 value 属性用以单独设置有效期
        if (array.length > 1) {
            long ttl = Long.parseLong(array[1]);
            cacheConfig = cacheConfig.entryTtl(Duration.ofSeconds(ttl));
        }
        return super.createRedisCache(name, cacheConfig);
    }
}

MyRedisCacheManager 类逻辑如下,

  1. 继承 Spring Cache 提供的 RedisCacheManager 类。
  2. 重写 createRedisCache(String name, RedisCacheConfiguration cacheConfig) 方法。
  3. 解析 name 参数,根据 # 字符串进行分割,获取缓存 key 名称以及缓存有效期。

接着我们修改下 CacheConfig 类的 cacheManager 方法用以使用 MyRedisCacheManager 类。代码如下,

@Bean
public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
    return new MyRedisCacheManager(RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory), defaultCacheConfig());
}

private RedisCacheConfiguration defaultCacheConfig() {
    return RedisCacheConfiguration.defaultCacheConfig()
            .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(keySerializer()))
            .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(valueSerializer()))
            .computePrefixWith(name -> CACHE_PREFIX + name  + ":")
            .entryTtl(Duration.ofSeconds(600));
}

最后我们修改下 @Cacheable 注解使用方式,在原有 value 属性的 configCache 值后添加 #600,单独标识缓存有效期。代码如下,

@Cacheable(value = "configCache#600", key = "#root.methodName + '_' + #root.args[0]")
@Override
public String getValueByKey(String key) {
   ...
}

看下 getValueByKey 方法生成的 Redis 缓存 key 有效期是多久。如下,

OK,看到是 590 秒有效期后,我们就大功告成了,希望本文能对大家有所帮助。


欢迎加入我的知识星球,全面提升技术能力。

👉 加入方式,长按”或“扫描”下方二维码噢

星球的内容包括:项目实战、面试招聘、源码解析、学习路线。

文章有帮助的话,在看,转发吧。

谢谢支持哟 (*^__^*)

微信扫码关注该文公众号作者

戳这里提交新闻线索和高质量文章给我们。
相关阅读
缓存之美 —— 如何选择合适的本地缓存?太香了!羊毛界中的爱马仕,不到百元就能入手!Preparing for the 2023 Tax Year: Ensuring a Strong Tax Saving?Java 近期新闻:JDK 22 的 JEP、Spring Shell、Quarkus、Apache Camel、JDKMon团|双十一提前享!内部福利价真的太香了!雪季开板ing,滑雪热身课程大放送...$50/2h的早鸟价也太香了吧!火了400年的老国货太香了!4周抚平眼纹!平价出奇迹!国外超火的户外运动智能手表!功能性、实用性、颜值都不输大牌,太香了!旅美散记(24):巧遇橡树林美到开挂!Halton这20+个秋季玩法真的太香了!K老K氧化的南非国宝博士茶,无咖啡因真是太香了(明10点开团)PPT里只有3段话怎么排版?我精心修改了10个版本,实在是太骚气了!低门槛、可转正!大厂寒假实习岗位太香了!HengChang ShaoFang · Hurun China Rich List 2023我,万年老主治,还没SCI,被90后医生比下去了,实在是太惨了......放弃魔都顶流国际校,她去买伦敦Top2私校“学区房”了,太香了!【五律】挪威琅琊榜仙境巧遇竹韵诗友轻松搞定 Spring 集成缓存,让你的应用程序飞起来!K老K氧化的南非国宝博士茶,无咖啡因真是太香了|开团火了400年的老国货太香了!4周抚平眼纹!平价出奇迹一百五十七 耦园Java近期新闻:Spring Framework 6.1、Spring Data 2023.1、Payara Platform可怕!美国超级大雾引发连环车祸,158辆车相撞,现场实在是太惨烈....火了400年的老国货太香了!轻松解决眼纹,40岁老阿姨也能抹出少女眼!【汉宫春】雨夜孤独 Han Palace Spring: Lonely Night in the Rain降级消费太香了!颜值不输大牌,还是植鞣牛皮,背上身满满高级感牛牛说:“我也不想吃那么多,这肉太香了!”《癸卯中秋有咏并序》淘宝绝对不会给你推荐的年货零食,9块9的那个太香了!Chasing Calm: The Rising Cost of Spiritual Healing in China张小斐的人设,实在是太假了伊能静晒儿子3年读完NYU!明星娃都爱的美本提前毕业,太香了!我写的第一本英文书 'The Story of Rice'一机多用的养生壶太香了!火锅、泡面、冲奶、炖煮样样精通薅羊毛太香了!纯羊毛打底衫,不到百元就能入手!“网友那些拍案叫绝的临场反应!”实在是太骚了...
logo
联系我们隐私协议©2024 redian.news
Redian新闻
Redian.news刊载任何文章,不代表同意其说法或描述,仅为提供更多信息,也不构成任何建议。文章信息的合法性及真实性由其作者负责,与Redian.news及其运营公司无关。欢迎投稿,如发现稿件侵权,或作者不愿在本网发表文章,请版权拥有者通知本网处理。