SpringBoot整合Redis实现声明式缓存

超详细的Java知识点路线图


前言

掌握了Redis的几大数据类型后,本章我们将学习在Java项目中如何使用Redis实现缓存。

编程式缓存

通过SpringBoot整合Redis的方式来实现缓存商品。
1)导入Redis依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

2)添加配置文件

spring.redis.host=localhost
spring.redis.port=6379
spring.redis.database=0
spring.redis.jedis.pool.max-active=100
spring.redis.jedis.pool.max-wait=100ms
spring.redis.jedis.pool.max-idle=100
spring.redis.jedis.pool.min-idle=10

3)配置类
配置RedisTemplate

@Configuration
public class RedisConfig {

    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
        RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();
        template.setConnectionFactory(factory);
        // 配置序列化器
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(om);
        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
        // key采用String的序列化方式
        template.setKeySerializer(stringRedisSerializer);
        // hash的key也采用String的序列化方式
        template.setHashKeySerializer(stringRedisSerializer);
        // value序列化方式采用jackson
        template.setValueSerializer(jackson2JsonRedisSerializer);
        // hash的value序列化方式采用jackson序列化器
        template.setHashValueSerializer(jackson2JsonRedisSerializer);
        template.afterPropertiesSet();
        return template;
    }
}

4)使用RestTemplate
常用方法:

  • ValueOperations opsForValue() 获得string类型的操作对象
  • HashOperations opsForHash 获得hash类型的操作对象

ValueOperations操作对象

  • set(key,value) 保存key-value
  • Object get(key) 读取value

使用缓存的步骤:

  1. 先查询缓存
  2. 如果查到直接返回
  3. 如果查不到,查询数据库
  4. 数据库查到,保存缓存中
  5. 数据库查不到返回null
@Override
 public Goods findById(Long id) {
     ValueOperations<String, Object> ops = template.opsForValue();
     //先查缓存,缓存有,直接返回不执行同步块,提高效率
     Goods goods = (Goods ) ops.get("goods-"+id);
     if(goods == null) {
         //上锁,保证查询缓存,查询数据库,保存缓存同步执行
         synchronized (this) {
             //先查询缓存
             goods = (Goods ) ops.get("goods-" + id);
             //如果查到直接返回
             if (goods!= null) {
                 System.out.println("从缓存查到" + goods);
                 return goods;
             } else {
                 //如果查不到,查询数据库
                 System.out.println("缓存没有,查询数据库");
                 goods = goodsMapper.selectById(id);
                 if (goods!= null) {
                     //数据库查到,保存缓存中
                     System.out.println("数据库查到" + goods);
                     ops.set("goods-" + id, goods);
                     return goods;
                 }
             }
             System.out.println("数据库没有查到");
             return null;
         }
     }
     return goods;
 }

声明式缓存

编程式缓存使用复杂,代码侵入性高,推荐使用声明式缓存,通过注解来实现热点数据缓存。

1)在启动类上添加注解

//启动缓存
@EnableCaching

2)Redis的配置类

@Configuration
public class RedisConfig {

    @Bean
    public RedisCacheConfiguration provideRedisCacheConfiguration(){
        //加载默认配置
        RedisCacheConfiguration conf = RedisCacheConfiguration.defaultCacheConfig();
        //返回Jackson序列化器
        return conf.serializeValuesWith(
                RedisSerializationContext.SerializationPair
                .fromSerializer(new GenericJackson2JsonRedisSerializer()));
    }
}

3)缓存相关注解

  • @CacheConfig 使用在Service类上,可以配置缓存名称,如:
    @CacheConfig(cacheNames = “books”)
  • @Cacheable 使用在查询方法上,让方法优先查询缓存
  • @CachePut 使用在更新和添加方法上,数据库更新和插入数据后同时保存到缓存里
  • @CacheEvict 使用在删除方法上,数据库删除后同时删除缓存

注意:缓存的实体类必须实现序列化接口

案例:Reids缓存品牌

//配置缓存名称为brand
@CacheConfig(cacheNames = "brand")
@Service
public class BrandServiceImpl extends ServiceImpl<BrandMapper, Brand> implements IBrandService {

    @Autowired
    private BrandMapper brandMapper;

	//按分类查询品牌时进行缓存,缓存名称是brand-category,键是分类id
    @Cacheable(cacheNames = "brand-category",key = "T(String).valueOf(#cid)")
    @Override
    public List<Brand> findBrandsByCategory(Integer cid) {
        return brandMapper.selectBrandsByCategory(cid);
    }

	//缓存单个品牌
    @Cacheable(key = "T(String).valueOf(#id)")
    @Override
    public Brand findBrandById(Long id) {
        return this.getById(id);
    }

	//修改品牌时更新缓存
    @CachePut(key = "T(String).valueOf(#brand.id)")
    @Override
    public Brand saveBrand(Brand brand) {
        this.saveOrUpdate(brand);
        return brand;
    }

	//删除品牌时删除缓存
    @CacheEvict(key = "T(String).valueOf(#id)")
    @Override
    public void deleteBrand(Long id) {
        this.removeById(id);
    }

	//缓存分页
    @Cacheable(cacheNames = "brand-page",key = "T(String).valueOf(#page)")
    @Override
    public IPage<Brand> pageBrands(Long page) {
        return this.page(new Page<>(page,10));
    }
}

结束


大家如果需要学习其他Java知识点,戳这里 超详细的Java知识点汇总

  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

恒哥~Bingo

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值