缓存
Redis 缓存的操作由 Spring 提供,我们可以通过 RedisTemplate 与注解形式使用。
配置
spring:
# redis 配置
redis:
# 地址
host: 127.0.0.1
# 端口,默认为6379
port: 6379
# 数据库索引
database: 0
# 密码
password: pass
# 前缀
prefix: "foo:"
# 连接超时时间
timeout: 10s
jedis:
pool:
# 连接池中的最小空闲连接
min-idle: 0
# 连接池中的最大空闲连接
max-idle: 2
# 连接池的最大数据库连接数
max-active: 2
# #连接池最大阻塞等待时间(使用负值表示没有限制)
max-wait: -1ms
cache:
redis:
key-prefix: "foo:"
time-to-live: 3600000注意
需要特别注意,两个缓存前缀(高亮行)必须保持一致,且不能与其它项目相同。
RedisTemplate
RedisTemplate 是 Spring 提供的对各种 Redis 连接库(Jedis/JRedis/RJC)的封装,提供了统一的接口和功能增强。
相关操作进行了归类封装,针对不同的 Redis 数据类型封装为不同的 Operation 接口。
ValueOperations:简单K-V操作
SetOperations:set类型数据操作
ZSetOperations:zset类型数据操作
HashOperations:map类型的数据操作
ListOperations:list类型的数据操作
使用示例
@Autowired
private RedisTemplate redis
// 1、删除单个key
redis.delete(key);
// 2、删除多个key
public void deleteKey (String ...keys){
redis.delete(keys);
}
// 3、指定key的失效时间
redis.expire(key,time,TimeUnit.MINUTES);
// 4、根据key获取过期时间
redis.getExpire(key);
// 5、判断key是否存在
redis.hasKey(key);
//3、通过ValueOperations设置值
redis.opsForValue().set("StringKey", "StringVaule");
redis.opsForValue().set("StringValue","StringVaule",1, TimeUnit.MINUTES);
//3、通过ValueOperations获取值
String str3 = (String) redis.opsForValue().get("StringKey");Spring Cache
Spring Cache 更进一步,对各种缓存方案(redis/ehcache/jcache等)进行抽象封装,统一API。 同时与 AOP 紧密结合,使用注解即可轻松操作缓存。
缓存注解
| 注解 | 类别 | 说明 |
|---|---|---|
| @Cacheable | 设置缓存 | 将方法执行结果进行缓存,存在缓存则不再执行方法 |
| @CachePut | 设置缓存 | 将方法执行结果进行缓存,不影响方法执行 |
| @CacheEvict | 删除缓存 | 清除缓存 |
| @Caching | 组合操作 | 组合多个缓存操作注解 |
| @CacheConfig | 统一配置 | 类级别注解,比如统一设置cacheNames |
@Cacheable
根据方法对其返回结果进行缓存,下次请求时,如果缓存存在,则直接读取缓存数据返回;如果缓存不存在,则执行方法,并把返回的结果存入缓存中。一般用在查询方法上。
属性/方法名:
- cacheNames 缓存分组名,必填,作为缓存键一部分,可以根据它删除一组缓存
- value 同cacheNames
- key 可选属性,使用 SpEL 自定义缓存的key
- keyGenerator key的生成器。key/keyGenerator二选一使用
- condition 条件符合则缓存,使用 SpEL
- unless 条件符合则不缓存,使用 SpEL
- sync 是否使用异步模式,默认为false
@CachePut
使用该注解标志的方法,每次都会执行,并将结果存入指定的缓存中。其他方法可以直接从响应的缓存中读取缓存数据,而不需要再去查询数据库。一般用在新增方法上。
属性/方法名:
- value 同cacheNames
- cacheNames 缓存分组名,必填,作为缓存键一部分,可以根据它删除一组缓存
- key 可选属性,使用 SpEL 自定义缓存的key
- keyGenerator key的生成器。key/keyGenerator二选一使用
- condition 条件符合则缓存,使用 SpEL
- unless 条件符合则不缓存,使用 SpEL
@CacheEvict
使用该注解标志的方法,会清空指定的缓存。一般用在更新或者删除方法上
属性/方法名
- value 缓存名,必填,它指定了你的缓存存放在哪块命名空间
- cacheNames 与 value 差不多,二选一即可
- key 可选属性,使用 SpEL 自定义缓存的key
- keyGenerator key的生成器。key/keyGenerator二选一使用
- condition 条件符合则缓存,使用 SpEL
- allEntries 是否清空所有缓存,默认为 false。如果指定为 true,则方法调用后将立即清空所有的缓存
- beforeInvocation 是否在方法执行前就清空,默认为 false。如果指定为 true,则在方法执行前就会清空缓存
@Caching
该注解可以实现同一个方法上同时使用上述注解。
@CacheConfig
当我们需要缓存的地方越来越多,你可以使用@CacheConfig(cacheNames = {"cacheName"})注解在 class 之上来统一指定value的值,这时可省略value,如果你在你的方法依旧写上了value,那么依然以方法的value值为准。
使用示例
@Component
@CacheConfig(cacheNames = {"toys"}) // 假设缓存前缀已设置为"foo:",那么这时会继续拼接上“toys::"
public class CacheTestService {
// 默认根据方法所有参数生成key,空参数时应该手动设置key
@Cacheable("'list'")
public Map getList(){
System.out.println("call db exec list");
Map<String, String> map = new HashMap<>();
map.put("p1", "hello");
map.put("p2", "world");
return map;
}
@CacheEvict(allEntries = true) // 删除所有toys分组内缓存
public void addOne(String id, String name){
System.out.println("call add one");
}
}可以看到,使用注解操作缓存非常清爽,对业务没有侵入性。推荐使用此方式,但需要注意仔细设计缓存key,防止缓存过多。