c# redis 如何设置过期时间_Spring cache整合Redis,并给它一个过期时间!
小Hub领读:
不知道你们有没给cache设置过过期时间,来试试?
上一篇文章中,我们使用springboot集成了redis,并使用RedisTemplate来操作缓存数据,可以灵活使用。
我才懂!SpringBoot的StringRedisTemplate与RedisTemplate的序列化策略有啥不同~
今天我们要讲的是Spring为我们提供的缓存注解Spring Cache。Spring支持多种缓存技术:RedisCacheManager、EhCacheCacheManager、GuavaCacheManager等,使用之前需要配置一个CacheManager的Bean。
配置好之后使用常用的三个注解来缓存数据:
@Cacheable
@CachePut
@CacheEvict。
这三个注解方别代表着什么意思,等会我们一一来解剖。
1、配置RedisCacheManager
刚才说了,首先我们需要配置一个缓存管理器,然后才能使用缓存注解来管理缓存。上一篇文章中我们已经整合了redis,接下来,我们只需要直接去配置RedisCacheManager即可。
com.markerhub.config.RedisConfig
/**
* 配置一个CacheManager才能使用@Cacheable等注解
*
* 公众号:MarkerHub
*/
@Bean
public CacheManager cacheManager(RedisTemplate<String, Object> template) {
// 基本配置
RedisCacheConfiguration defaultCacheConfiguration =
RedisCacheConfiguration
.defaultCacheConfig()
// 设置key为String
.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(template.getStringSerializer()))
// 设置value 为自动转Json的Object
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(template.getValueSerializer()))
// 不缓存null
.disableCachingNullValues()
// 缓存数据保存1小时
.entryTtl(Duration.ofHours(1));
// 够着一个redis缓存管理器
RedisCacheManager redisCacheManager =
RedisCacheManager.RedisCacheManagerBuilder
// Redis 连接工厂
.fromConnectionFactory(template.getConnectionFactory())
// 缓存配置
.cacheDefaults(defaultCacheConfiguration)
// 配置同步修改或删除 put/evict
.transactionAware()
.build();
return redisCacheManager;
}
上面的配置中,大部分代码都给出了注释,我们只需要根据需求配置一下即可。其中反序列策略延用了原来RedisTemplate的参数。
RedisCacheConfiguration
RedisCacheManager
还有一个重要的步骤不能忘记了,需要开启Spring Cache的缓存功能支持,很简单,只需要在RedisConfig上添加一个注解:
@EnableCaching
写一个例子
上面我们已经已经配置了RedisCacheManager帮我们管理缓存,接下来我们就去使用Spring Cache的注解来完成我们的代码测试。
下面的例子我写得可能有点粗,如果你对一些参数还不了解,建议你看看这篇文章: https://blog.csdn.net/dreamhai/article/details/80642010
。
1、@Cacheable
标记在方法或者类上,标识该方法或类支持缓存。Spring调用注解标识方法后会将返回值缓存到redis,以保证下次同条件调用该方法时直接从缓存中获取返回值。这样就不需要再重新执行该方法的业务处理过程,提高效率。
@Cacheable常用的三个参数如下:
cacheNames 缓存名称
key 缓存的key,需要注意key的写法哈
condition 缓存执行的条件,返回true时候执行
@Slf4j
@Service
public class UserServiceImpl implements UserService {
@Override
@Cacheable(cacheNames = "cache_user", key="'user_' + #id")
public User getById(long id) {
log.info("进来查库了--------->{}", id);
User user = new User();
user.setId(1L);
user.setUsername("MarkerHub" + id);
return user;
}
}
然后写一个具体的调用:
@RestController
public class UserController {
@Autowired
UserService userService;
@GetMapping("/u/{id}")
public User index(@PathVariable("id") Long id) {
User user = userService.getById(id);
return user;
}
}
测试下访问结果,访问链接: http://localhost:8080/u/12
,
第一次调用时候控制台输出:
进来查库了--------->12
第二次再访问的时候,就没有再输出,说明没有进入业务方法,就是在redis中获取结果直接返回。
看一下redis的可视化工具:
这里大家需要注意一下,在配置redis的序列化方式的时候,一定要配置下面的代码,这个在之前Springboot配置redis中已经说过了。
Jackson2JsonRedisSerializer<Object> serializer = new Jackson2JsonRedisSerializer<Object>(Object.class);
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
serializer.setObjectMapper(objectMapper);
如果你序列化之后的value只是一个简单的json数据,这样会引起强转错误的。需要注意一下!
2、@CacheEvict
标记在方法上,方法执行完毕之后根据条件或key删除对应的缓存。常用的属性:
allEntries boolean类型,表示是否需要清除缓存中的所有元素
key 需要删除的缓存的key
@Override
@CacheEvict(cacheNames = "cache_user", allEntries = true)
public void update(User user) {
// 更新逻辑...
}
于是, update
方法执行之后, cacheNames="cache_user"
里面的所有缓存都会被删除!这也是很常用的方法。当然了,你还可以这样写,根据key来删除某个指定缓存:
@Override
@CacheEvict(cacheNames = "cache_user", key = "'user_' + #user.id")
public void update(User user) {
// 更新逻辑...
}
3、@@CachePut
标注的方法在执行前不会去检查缓存中是否存在之前执行过的结果,而是每次都会执行该方法,并将执行结果以键值对的形式存入指定的缓存中。
4、@Caching
可以在一个注解上标注多种注解,其拥有三个属性:cacheable、put和evict,分别用于指定@Cacheable、@CachePut和@CacheEvict
过期时间
我们已经实现了Spring Cache的基本功能,整合了Redis作为 RedisCacheManger
,但众所周知,我们在使用 @Cacheable
注解的时候是无法给缓存这是过期时间的。但有时候在一些场景中我们的确需要给缓存一个过期时间!
在缓存与库数据不一致的时候,自动过期就显得尤为重要,这是一个保底的方式。那么,如何给Spring cache一个过期时间呢?
其实不需要我们去整合第三方的包,比如Redission等,我们在配置 RedisCacheManager
的时候其实就可以配置过期时间,只是,这个过期时间是针对cache的。
这是什么意思?比如你使用了如下注解:
@Cacheable(cacheNames = "cache_user", key="'user_' + #id")
我们可以在初始化的时候指定cacheNames为 cache_user
的cache的过期时间。我们先来回顾一下 RedisCacheManager
的初始化配置。
上面在 RedisCacheConfiguration
上我们配置一个关于过期时间的配置 .entryTtl(Duration.ofHours(1))
,缓存数据保存一个小时。并且在 RedisCacheManager
上通过 .cacheDefaults(defaultCacheConfiguration)
进行了配置。这两行代码其实是在说,所有的缓存数据默认保存一个小时。
相比于以前,我们统一配置了缓存的过期时间是1个小时。但这还是写得比较固定,一般来说,我们想给不同的cache不同的过期时间,比如 cache_post
和 cache_user
不一样的过期时间,那么这个怎么弄呢?能否在配置中实现吗?
答案是可以的,很简单,在 RedisCacheManager
中有这个方法:
RedisCacheManagerBuilder withCacheConfiguration(String cacheName, RedisCacheConfiguration cacheConfiguration)
可以给每个cacheName不同的RedisCacheConfiguration,之前的配置,我们是配置了一个默认的缓存配置,有个这个方法之后,我们就可以指定某个cache的缓存配置。每个缓存配置的不同的地方其实就是过期时间。因此,我们抽个方法出来生成缓存配置,代码如下:
RedisCacheConfiguration getCacheConfigurationWithTtl(RedisTemplate<String, Object> template, long seconds) {
return RedisCacheConfiguration
.defaultCacheConfig()
// 设置key为String
.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(template.getStringSerializer()))
// 设置value 为自动转Json的Object
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(template.getValueSerializer()))
// 不缓存null
.disableCachingNullValues()
// 缓存数据保存1小时
.entryTtl(Duration.ofSeconds(seconds));
}
参数seconds指定缓存的过期时间,因此,我们在RedisCacheManager中应该这样配置:
RedisCacheManager redisCacheManager =
RedisCacheManager.RedisCacheManagerBuilder
// Redis 连接工厂
.fromConnectionFactory(template.getConnectionFactory())
.cacheDefaults(getCacheConfigurationWithTtl(template, 60 * 60))
.withCacheConfiguration("cache_user", getCacheConfigurationWithTtl(template, 60))
.withCacheConfiguration("cache_post", getCacheConfigurationWithTtl(template, 120))
// 配置同步修改或删除 put/evict
.transactionAware()
.build();
return redisCacheManager;
}
根据上面的配置,我们指定了cacheName如下:
cache_user过期时间为60秒
cache_post过期时间为120秒
其他默认过期时间为1小时
这也是我建议大家的写法!
很多人还有其他实现写法,比如在cacheNames后面添加 #3600
,截取 #
后面的数字作为过期时间。
@Cacheable(cacheNames = "cache_user#3600", key="'user_' + #id")
更有一些人想给key一个过期时间,于是又有这种写法:
@Cacheable(cacheNames = "cache_user#3600", key="'user_' + #id + '#3600'")
其实在我看来没有必要。直接在配置中写好,简单方便!
结束语
好啦,今天的文章到此结束啦,右下角点个在看再走呗,哈哈。
(完)
MarkerHub文章索引:
https://github.com/MarkerHub/JavaIndex
【推荐阅读】
月薪10K、15K、20K的Java程序员分别需要掌握哪些技术?
传统@ServerEndpoint方式开发WebSocket应用和SpringBoot构建WebSocket应用程序
小白教程,Springboot项目搭建(前端到数据库,超详细)
Spring 和 Spring Boot 最核心的 3 大区别,详解!
就几条命令,一键学会Docker部署SpringBoot项目
好文!必须点赞
c# redis 如何设置过期时间_Spring cache整合Redis,并给它一个过期时间!相关推荐
- redis lettuce 超时_Spring Cache 操作 Redis 实现数据缓存(上)
点击上方☝SpringForAll社区 轻松关注!及时获取有趣有料的技术文章 本文来源:http://www.mydlq.club/article/55/ . 一.缓存概念知识 . 1.是什么缓存 . ...
- redis setnx 分布式锁_Spring Boot 整合 Redis 正确的实现分布式锁
前言 最近在做分块上传的业务,使用到了Redis来维护上传过程中的分块编号. 每上传完成一个分块就获取一下文件的分块集合,加入新上传的编号,手动接口测试下是没有问题的,前端通过并发上传调用就出现问题了 ...
- mysql springboot 缓存_Spring Boot 整合 Redis 实现缓存操作
摘要: 原创出处 www.bysocket.com 「泥瓦匠BYSocket 」欢迎转载,保留摘要,谢谢! 『 产品没有价值,开发团队再优秀也无济于事 – <启示录> 』 本文提纲 一.缓 ...
- RedisTemplate操作redis五大类型用法详解(springboot整合redis版本)
1.案例说明 springboot整合redis之后,提供了操作redis的简便方式 通过通用对象redisTemplate方式操作String,Hash,List,Set SortSet五大数据类型 ...
- springboot session默认失效时间_Spring Boot 整合 Redis,用起来真简单
来源:http://rrd.me/epDTz Redis 是目前业界使用最广泛的内存数据存储.相比 Memcached,Redis 支持更丰富的数据结构,例如 hashes, lists, sets ...
- redistemplate set方法_spring boot整合redis ---- RedisTemplate 三分钟快速入门
引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spri ...
- redis 值字符串前面部分乱码_StringBoot 整合Redis解决存储乱码(通过StringRedisSerializer来进行序列化)...
org.springframework.boot spring-boot-starter-redis 1.4.7.RELEASE 注意: spring-boot-starter-data-redis ...
- 缓存(cache、Redis)
缓存(Cache,Redis) 1.pom <?xml version="1.0" encoding="UTF-8"?> <project x ...
- SpringBoot整合Redis并实现Redis工具类
Redis 是用 C 语言开发的一款开源的.高性能的键值对存储数据库.它采用 BSD 协议,为了适应不同场景下的存储需求,提供了多种键值对类型,到目前为止 Redis 数据库支持5种数据类型,分别是S ...
最新文章
- html中#include file的使用方法
- JavaScript对象,方括号和算法
- checkstyle安装使用
- 电容和频率的关系_为什么会有直流电和交流电?频率为什么是50hz?白话科普专业知识...
- Mysql之alter用法汇总
- C语言对p1口取反,单片机c语言编程基础(5页)-原创力文档
- 天正建筑lisp编程接口_编程思想|面向过程的结构化、面向对象的抽象化、泛型编程...
- 这五张PPT告诉你,如何打造无人驾驶“最强大脑”
- [批处理]截取for命令里面的变量%%i
- 算法导论 思考题12-1
- Linux curl命令简介
- 压箱底的Android UI开源库(一)
- mysql 分页_MySQL如何实现分页查询
- 【Python-利用动态二维码传输文件(三)】动态二维码展示界面制作,涉及PIL库、threading库、os库、time库和tkinter库的Tk、Label组件
- WAIC | 阿里龙志勇:云游戏量变进行时,与元宇宙有什么关系?
- 使用weinre调试手机页面
- TOA(tcp option adress)安装
- 新的放假规定,大年三十还得朝九晚五!
- 菜鸟弱弱地问:找个薪资待遇差的工作能成长吗?
- P5236 【模板】静态仙人掌(仙人掌圆方树)