您当前的位置: 首页 >  缓存

SpringBoot 整合 SpringCache 使用Redis(使用 lettuce)实现查询缓存

梁云亮 发布时间:2020-04-30 21:53:43 ,浏览量:3

第一步:创建SpringBoot项目 maven依赖

	org.springframework.boot
    spring-boot-starter-web

有的文章说需要再加入依赖spring-boot-starter-cache,实际测试spring-boot-starter-web中已经包含了spring cache相关的依赖。

application.yml
spring:
  redis:
    database: 0
    host: 127.0.0.1
    port: 6379
    #    password: 1234
    timeout: 10000ms  # 超时时间
    lettuce:
      pool:
        max-idle: 8 # 最大空闲连接数,默认值为8
        max-wait: -1ms # 最大连接阻塞等待时间,默认值-1
        min-idle: 2 # 最小空闲连接数
        max-active: 20 #最大连接数
  cache:
    type: redis #缓存类型
    redis:
      cache-null-values: false #不缓存null数据
      time-to-live: 50000ms #超时时间
      use-key-prefix: false #不使用前缀
第二步:Cache配置文件
//启用Redis缓存,这个注释必须加上,即使单元测试也得加上
@EnableCaching
@Configuration
public class CacheRedisConfig {
    /**
     * 过期时间7天
     */
    private final Duration timeToLive = Duration.ofDays(7);

    private final StringRedisSerializer keySerializer = new StringRedisSerializer();

    /**
     * 使用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值(默认使用JDK的序列化方式)
     */
    private final Jackson2JsonRedisSerializer valueSerializer = new Jackson2JsonRedisSerializer(Object.class);

    /**
     * 代码块,会优先执行
     * 用来设置Jackson2JsonRedisSerializer
     */ {
        ObjectMapper objectMapper = new ObjectMapper();
        //设置所有访问权限以及所有的实际类型都可序列化和反序列化
        objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        // 指定序列化输入的类型,类必须是非final修饰的
        objectMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance,
                ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);

        //下面两行解决Java8新日期API序列化问题
        objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
        objectMapper.registerModule(new JavaTimeModule());

        valueSerializer.setObjectMapper(objectMapper);
    }

    /**
     * 由于原生的redis自动装配,在存储key和value时,没有设置序列化方式,故自己创建redisTemplate实例
     *
     * @param factory
     * @return
     */
    @Bean(name = "redisTemplate")
    public RedisTemplate redisTemplate(RedisConnectionFactory factory) {
        RedisTemplate template = new RedisTemplate();
        template.setConnectionFactory(factory);

        // key采用String的序列化方式
        template.setKeySerializer(keySerializer);
        // hash的key也采用String的序列化方式
        template.setHashKeySerializer(keySerializer);
        // value序列化方式采用jackson
        template.setValueSerializer(valueSerializer);
        // hash的value序列化方式采用jackson
        template.setHashValueSerializer(valueSerializer);
        template.afterPropertiesSet();
        return template;
    }

    @Bean(name = "cacheManager")
    public RedisCacheManager cacheManager(RedisConnectionFactory factory) {
        // 配置序列化(解决乱码的问题),通过config对象对缓存进行自定义配置
        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
                // 设置缓存的默认过期时间
                .entryTtl(timeToLive)
                .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(keySerializer))
                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(valueSerializer))
                // 不缓存空值
                .disableCachingNullValues();

        //根据redis缓存配置和reid连接工厂生成redis缓存管理器
        RedisCacheManager redisCacheManager = RedisCacheManager.builder(factory)
                .cacheDefaults(config)
                .transactionAware()
                .build();
        return redisCacheManager;
    }

    /**
     * 配置事务管理器
     *
     * @param dataSource
     * @return
     */
    @Bean
    public PlatformTransactionManager transactionManager(DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }

}

在SpringBoot2.0之后,spring容器自动的生成了StringRedisTemplate和RedisTemplate,可以直接注入。但是在实际使用中,大多情况下不会直接使用RedisTemplate,而是会对key和value进行序列化,所以我们还需要新增一个配置类。

第三步:Redis工具类

参看博客:Redis工具类:RedisTemplate

第四步:实体类:
@Getter
@Setter
@ToString
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class Province implements Serializable {
    private static final long serialVersionUID = -7311767494745575164L;
    /**
     * 编号
     */
    @ApiModelProperty(value = "编号")
    private Integer id;
    /**
     * 省名
     */
    @ApiModelProperty(value = "省名")
    private String name;
    /**
     * 所属地区
     */
    @ApiModelProperty(value = "所属地区")
    private String area;
    /**
     * 显示优先级
     */
    @ApiModelProperty(value = "显示优先级")
    private Integer priority;
    /**
     * 状态 1正常 0删除
     */
    @ApiModelProperty(value = "状态 1正常 0删除")
    private Integer status;
}
第五步:Service 接口及实现类:

使用MyBatisPlus实现

DeptService.java
public interface ProvinceService extends IService {
    /**
     * 添加省份
     *
     * @param province
     * @return 返回修改后的省份
     */
    Province insertProvince(Province province, Boolean flag);

    /**
     * 根据id查找省份
     *
     * @param id
     * @return
     */
    Province findProvinceById(Integer id, Boolean flag);

    /**
     * 从Redis中查找所有的省份
     *
     * @return
     */
    List findAllProvince(String key, Boolean flag);

    /**
     * 修改省份
     *
     * @param province
     * @return 返回修改后的省份
     */
    Province updateProvince(Province province, Boolean flag);


    /**
     * 删除id指定的省份
     *
     * @param id
     * @return
     */
    Province deleteProvinceById(Integer id, Boolean flag);
}
DeptServiceImpl.java
@Service
@CacheConfig(cacheManager = "cacheManager")
public class ProvinceServiceImpl extends ServiceImpl implements ProvinceService {
    @Resource
    private RedisUtil provinceListRedisUtil;

    @Override
    @Cacheable(value = RedisConst.PROVINCE, key = "#key", condition = "#flag==true")
    public List findAllProvince(String key, Boolean flag) {
        List provinceList = baseMapper.selectList(null);
        return provinceList;
    }

    @Override
    @CachePut(value = RedisConst.PROVINCE, key = "#province.id", condition = "#flag==true")
    public Province insertProvince(Province province, Boolean flag) {
        int insertRes = baseMapper.insert(province);
        if (insertRes == 1) {
            //更新Province列表
            List provinceList = provinceListRedisUtil.get(RedisConst.PROVINCE + "::all");
            provinceList.add(province);
            //排序
            provinceList.sort((item1, item2) -> {
                int t1 = item1.getPriority() == null ? 0 : item1.getPriority();
                int t2 = item2.getPriority() == null ? 0 : item2.getPriority();
                return t2 - t1;
            });
            provinceListRedisUtil.set(RedisConst.PROVINCE + "::all", provinceList);
        }
        return province;
    }

    @Override
    @Cacheable(value = RedisConst.PROVINCE, key = "#id", condition = "#flag==true")
    public Province findProvinceById(Integer id, Boolean flag) {
        Province province = baseMapper.selectById(id);
        return province;
    }

    @Override
    @CachePut(value = RedisConst.PROVINCE, key = "#province.id", condition = "#flag==true")
    public Province updateProvince(Province province, Boolean flag) {
        int updateRes = baseMapper.updateById(province);
        if (updateRes == 1) {
            province = baseMapper.selectById(province.getId());
            //目标城市下的所有Province
            List provinceList = provinceListRedisUtil.get(RedisConst.PROVINCE + "::all");
            for (int i = 0; i             
关注
打赏
1688896170
查看更多评论
0.0516s