使用springCache简化缓存开发

  1. 导入依赖

    <dependency>
    	<groupId>org.springframework.boot</groupId>
    	<artifactId>spring-boot-starter-cache</artifactId>
    </dependency>
    <dependency>
    	<groupId>org.springframework.boot</groupId>
    	<artifactId>spring-boot-starter-data-redis</artifactId>
    </dependency>
    
  2. 配置使用redis作为缓存

    spring:
    	cache:
    		type: redis
    	redis:
    	    # 存活时间/过期时间:60s
    	    time-to-live: 60000
    	    # 缓存中的key前缀.如果指定了前缀就用我们指定的前缀,如果没有就默认使用缓存的名字作为前缀
    	    key-prefix: CACHE_
    	    # 是否使用key前缀
    	    use-key-prefix: true
    	    # 是否缓存空值,防止缓存穿透
    	    cache-null-values: true
    
  3. springCache缓存相关注解

  • @Cacheable: 触发将数据保存到缓存的操作
    如果缓存中有该注解标识方法的返回结果,则不会调用;否则将方法的结果放入缓存
  • @CacheEvict: 触发将数据从缓存删除的操作
    • @CacheEvict(value = “category”, allEntries = true)指定删除category分区下的所有数据
  • @CachePut: 不影响方法执行更新缓存(可以应用于双写模式:更新数据库的同时将方法的返回值用于更新缓存)
  • @Caching: 组合以上多个操作
  • @CacheConfig: 在类级别共享缓存的相同配置
  • @Caching: 同时进行多种缓存操作,比如同时删除多个缓存
  1. 自定义redis cache配置类(包括开启缓存功能: @EnableCaching)

    package com.kenai.gulimall.product.config;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.autoconfigure.cache.CacheProperties;
    import org.springframework.boot.context.properties.EnableConfigurationProperties;
    import org.springframework.cache.annotation.EnableCaching;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.data.redis.cache.RedisCacheConfiguration;
    import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
    import org.springframework.data.redis.serializer.RedisSerializationContext;
    import org.springframework.data.redis.serializer.StringRedisSerializer;
    
    @EnableConfigurationProperties(CacheProperties.class)
    @Configuration
    @EnableCaching
    public class MyCacheConfig {
        @Autowired
        private CacheProperties cacheProperties;
    
        /**
         * 不使用上面的自动注入,在方法的参数中加上CacheProperties cacheProperties也可以
         * @return
         */
        @Bean
        public RedisCacheConfiguration redisCacheConfiguration(){
            RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig();
            // 指定key的序列化方式:string的UTF-8编码
            // 指定value的序列化方式为json。这样在redis缓存中便可以看到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;
        }
    }
    
  2. @Cacheable注解的使用

    @Override
    // 注解中value对应的category表示缓存要放入的分区(按照业务类型分)
    // 如果该方法的返回结果没有放入缓存,则会将缓存放入category分区中,否则不进行操作
    // key默认自动生成,也可以指定,接收一个SPEL(spring表达式语言)
    @Cacheable(value = {"category"}, key = "'level1Categorys'")
    public List<CategoryEntity> getLevel1Categorys() {
        log.info("调用getLevel1Categorys方法");
        List<CategoryEntity> categoryEntities = this.baseMapper.selectList(new QueryWrapper<CategoryEntity>().eq("parent_cid", 0));
        return categoryEntities;
    }
    
  3. redis中缓存数据展示
    在这里插入图片描述
    虽然格式不太友好,但是可以看出是json格式

  4. @CacheEvict注解的使用

    /**
     * 级连更新所有关联数据
     * @param category
     */
    // 当更新数据库时,会删除redis缓存中的数据,当下次查询时再进行缓存
    @CacheEvict(value = "category", key = "'level1Categorys'")
    @Override
    @Transactional
    public void updateCascade(CategoryEntity category) {
        this.updateById(category);
        if(!StringUtils.isEmpty(category.getName())){
            categoryBrandRelationService.updateCategory(category.getCatId(), category.getName());
        }
    }
    
  5. springCache总结

  • @Cacheable的sync=true的时候,多个线程尝试用相同的key去缓存拿数据的时候,会是一个同步的操作(本质上使用了本地锁synchornized),可以解决缓存击穿的问题(大量并发进来同时查询一个正好过期的数据).
  • 其他时候,比如在缓存数据和删除缓存的时候并没有使用锁机制.
  • 总结1: 对于常规数据(读多写少,即时性、一致性要求不高的数据),完全可以使用springCache
  • 总结2: 对于特殊数据,特殊设计
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值