springboot中cache的使用
配置redis实现缓存
1 依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
2 开启对缓存的支持
@EnableTransactionManagement
@SpringBootApplication
@EnableCaching //开启对缓存的支持
public class BlogApplication {
public static void main(String[] args) {
SpringApplication.run(BlogApplication.class, args);
}
}
3 相关注解
1 @Cacheable:触发将数据保存到缓存中的操作。
2 @CacheEvict:触发将数据从缓存中删除的操作。
3 @CachePut:不影响方法执行更新缓存。
4 @Caching:配置于函数上,组合以上多个操作。
5 @CacheConfig:在类级别共享缓存的相同配置。
6 @Cacheable :缓存数据
/**
* @Cacheable 每一个需要缓存的数据我们都来指定要放到哪个名字的缓存中【缓存的分区(按业务类型来分)】
* 代表当前的结果需要缓存,如果缓存中有,方法不用调用,如果缓存中没有,则调用方法并将结果放入缓存中
* 默认行为:
* 1)、如果缓存中有,方法不会调用
* 2)、key默认自动生成,缓存的名字::SimpleKey{}(自动生成的key值)
* 3)、缓存的value的值,默认使用java序列化机制,将序列化后的结果放入缓存中
* 4)、默认ttl时间:-1(即永不过期)
* 自定义:
* 1)、指定缓存中key的值, key属性指定,接受一个SpEl
* SpEl参考地址:https://docs.spring.io/spring-framework/docs/5.2.19.RELEASE/spring-framework-reference/integration.html#cache-spel-context
* 2)、设置数据的有效时间
* 3)、将数据保存为json格式
* 原理:CacheAutoConfiguration -> RedisCacheConfiguration -> 自动配置了RedisCacheManager
* -> 初始化所有的缓存 -> 每个缓存决定使用什么配置 -> 如果RedisCacheConfiguration中有就用已有的,没有就用默认的配置
* -> 想改缓存的配置,只需要给容器中放一个RedisCacheConfiguration即可
* ->就会应用到当前RedisCacheConfiguration管理的所有缓存分区中
*/
@Cacheable(value = {"category"},key = "#root.method.name") //指定方法名称为key值,key的值为字符串时需要加上单引号
@CachePut : 更新缓存的数据
/**
* @CacheEvict 失效模式
* 修改完成后,自动将相应的缓存删除
* @CacheEvict(value = {"category"},allEntries = true) 指定删除某个分区下的所有数据
*/
@CacheEvict(value = {"category"},key = "'info'") //key的值为字符串时需要加上单引号
@CacheEvict : 删除缓存的数据
/**
* @CacheEvict 失效模式;修改完成后,自动将相应的缓存删除
* @Caching 同时进行多种缓存操作
*/
//@CacheEvict(value = {"category"},key = "'info'") //key的值为字符串时需要加上单引号
@Caching(evict ={
@CacheEvict(value = {"category"},key = "'info'"),
@CacheEvict(value = {"category"},key = "'getById'")
})
@Cacheable/@CachePut/@CacheEvict 主要的参数
名称 解释
value 缓存的名称,在 spring 配置文件中定义,必须指定至少一个
例如:
@Cacheable(value=”mycache”) 或者
@Cacheable(value={”cache1”,”cache2”}
key 缓存的 key,可以为空,如果指定要按照 SpEL 表达式编写,
如果不指定,则缺省按照方法的所有参数进行组合
例如:
@Cacheable(value=”testcache”,key=”#id”)
condition 缓存的条件,可以为空,使用 SpEL 编写,返回 true 或者 false,
只有为 true 才进行缓存/清除缓存
例如:@Cacheable(value=”testcache”,condition=”#userName.length()>2”)
unless 否定缓存。当条件结果为TRUE时,就不会缓存。
@Cacheable(value=”testcache”,unless=”#userName.length()>2”)
allEntries
(@CacheEvict ) 是否清空所有缓存内容,缺省为 false,如果指定为 true,
则方法调用后将立即清空所有缓存
例如:
@CachEvict(value=”testcache”,allEntries=true)
beforeInvocation
(@CacheEvict) 是否在方法执行前就清空,缺省为 false,如果指定为 true,
则在方法还没有执行的时候就清空缓存,缺省情况下,如果方法
执行抛出异常,则不会清空缓存
例如:
@CachEvict(value=”testcache”,beforeInvocation=true)
4 为相关类添加注解
//部分代码测试用
@Cacheable(value = "login",key = "#username")
@RequestMapping("/toLogin")
public String login(@NotNull(message = "用户名不能为空") String username, @NotNull String password, Model model){
admin = loginService.finduserByName(username);}
5 测试
访问相关接口
查看缓存数据
6 自定义配置
#缓存数据的存活时间,默认单位毫秒
spring.cache.redis.time-to-live=60000
#如果指定了前缀就用我们指定的前缀,如果没有设置就默认使用缓存的名字作为前缀
spring.cache.redis.key-prefix=CACHE_
#是否启用前缀功能
spring.cache.redis.use-key-prefix=true
#是否缓存null值,防止缓存穿透
spring.cache.redis.cache-null-values=true
7 将数据保存为json格式
@EnableConfigurationProperties({CacheProperties.class}) //让配置文件中的配置生效
@Configuration
public class MyCacheConfig {
@Bean
RedisCacheConfiguration redisCacheConfiguration(CacheProperties cacheProperties){
//默认配置
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig();
//key序列化,需要将原来的配置覆盖掉,此处可参考源码
config = config.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()));
//value序列化,需要将原来的配置覆盖掉,此处可参考源码
config = config.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()));
//将配置文件中的所有配置都生效
CacheProperties.Redis redisProperties = cacheProperties.getRedis(); //redis相关的所有配置
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;
}
}
8 总结
尽量不在配置文件中设置前缀
存储同一类型的数据,都可以指定成同一个分区。分区名默认就是缓存的前缀,如@Cacheable(value = {“category”},key = “#root.method.name”)中的value值就是分区名。
@CachePut 是双写模式
缓存穿透解决:配置文件中配置 spring.cache.redis.cache-null-values=true
缓存击穿解决:@Cacheable(value = {“category”},key = “#root.method.name”,sync = true) 【sync = true 加锁】
常规数据(读多写少,一致性、即时性要求不高的数据),完全可以使用springCache;写模式只要数据有缓存时间就可以了。
特殊数据:特殊设计