一、Spring Cache整合服务
1.pom.xml
<!--spring catch-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
2.application.properties
#开启缓存空值,防止缓存穿透,true-如果方法返回Null则存入null
spring.cache.redis.cache-null-values=true
#缓存类型
spring.cache.type=redis
#ttl过期时间,时间结束自动删除缓存数据
spring.cache.redis.time-to-live=3600000
#(不推荐使用,默认前缀为缓存名,方便区分)指定key前缀,区分key
spring.cache.redis.key-prefix=CACHE_
#确认开启key前缀
spring.cache.redis.use-key-prefix=true
#开启缓存空值,防止缓存穿透,如果方法返回Null则想缓存存入null
spring.cache.redis.cache-null-values=true
3.在方法返回参数上加注解@Cacheable,方法返回的数据就会存入redis缓存
@Cacheable(name:缓存名,key:缓存的key)
缓存下面用key区分方法的返回值
@Cacheable(value = "category",key = "#root.method.name")//value 缓存名
@Override
public List<CategoryEntity> getCategory1Level() {
System.out.println("getLevel1Categorys........");
Long time = System.currentTimeMillis();
List<CategoryEntity> categoryEntities = this.getBaseMapper().selectList(new QueryWrapper<CategoryEntity>().eq("parent_cid", 0));
System.out.println("消耗时间:"+ (System.currentTimeMillis() - time));
return categoryEntities;
}
二、Spring Catch缓存的值是二进制的,自定义序列化配置转成JSON格式
如果值配置key和value的json格式,ttl就会失效,所以必须把全部配置带上
配置类注解
配置类
@EnableConfigurationProperties(CacheProperties.class)
@Configuration
@EnableCaching
public class SpringCacheConfig {
/**
* 配置文件的配置没有用上
* @return
*/
@Bean
public RedisCacheConfiguration redisCacheConfiguration(CacheProperties cacheProperties) {
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig();
// config = config.entryTtl();//TODO 缓存数据 二进制 -> json
config = config.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()));
config = config.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()));
CacheProperties.Redis redisProperties = cacheProperties.getRedis();
//将配置文件中所有的配置都生效
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;
}
}
三、如何使用Spring Cache
1.添加缓存进入redis:给需要缓存的方法加上注解@Cacheable,该方法的返回值就会存入缓存
@Cacheable(value = "category",key = "#root.method.name")//value 缓存名
@Override
public List<CategoryEntity> getCategory1Level() {
System.out.println("getLevel1Categorys........");
Long time = System.currentTimeMillis();
List<CategoryEntity> categoryEntities = this.getBaseMapper().selectList(new QueryWrapper<CategoryEntity>().eq("parent_cid", 0));
System.out.println("消耗时间:"+ (System.currentTimeMillis() - time));
return categoryEntities;
}
2.失效模式删除缓存:在方法上加上注解@CacheEvict,在做更新操作时删除缓存,保证缓存数据一致性
key是spel表达式,字符串必须加’’
//级联更新所有数据
@CacheEvict(value = "category",key = "'getCategory1Level'")//缓存失效,key是spel表达式,字符串必须加''
@Transactional//必须在MybatisConfig配置类中开启事务注解,才能使用这里的事务@Transactional
@Override
public void updateCasca(CategoryEntity category) {
//校验?
this.updateById(category);
//if (!StringUtils.isBlank(category.getName())){
categoryBrandRelationService.updateCategory(category.getCatId(),category.getName());
}
3.同时删除多个缓存
指定删除分区下所有缓存数据
这里要打开缓存前缀功能use-key-prefix: true,不然全部缓存数据都会删除
例:删除value = "category"下的全部缓存
4.双写模式
@CachePut
5.默认无锁,sync = true加上同步锁
@Cacheable(value = "category",key = "#root.method.name",sync = true)
四、摘要
每一个需要缓存的数据我们都来指定要放到那个名字的缓存。【缓存的分区(按照业务类型分)】
代表当前方法的结果需要缓存,如果缓存中有,方法都不用调用,如果缓存中没有,会调用方法。最后将方法的结果放入缓存
默认行为
如果缓存中有,方法不再调用
key是默认生成的:缓存的名字::SimpleKey::
缓存的value值,默认使用jdk序列化机制,将序列化的数据存到redis中
默认时间是 -1:
自定义操作:key的生成
指定生成缓存的key:key属性指定,接收一个Spel
指定缓存的数据的存活时间:配置文档中修改存活时间
将数据保存为json格式