SpringBoot2.0整合Redis作为缓存

第一步:安装Redis

在这里使用Docker安装Redis,Docker相关内容可以参考Docker快速入门。

1、下载redis镜像:可以使用Docker中国记性镜像加速(https://www.docker-cn.com/registry-mirror)。

docker pull registry.docker-cn.com/library/redis

2、运行镜像

 docker run -d -p 6379:6379 --name myredis registry.docker-cn.com/library/redis

3、查看运行情况

docker ps

4、使用RedisDesktopManager测试连接情况:

SpringBoot2.0整合Redis作为缓存_第1张图片

第二步:SpringBoot整合Redis,引入starter

        
            org.springframework.boot
            spring-boot-starter-data-redis
        

第三步:在application.yml中配置redis

spring:
  redis:
    host: 192.168.1.4
  ##还有好多其他配置

在这里,redis作为缓存的基本环境就配置结束了,下来测试一下redis作为缓存的操作。

第四步:测试缓存

在org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration中,为我们注入了
1、RedisTemplate redisTemplate k-v都是Object,对对象操作,默认JDK序列化方式
2、StringRedisTemplate stringRedisTemplate     k-v都是string,对字符串操作
因此我们可以使用这两个对Redis进行操作。

StringRedisTemplate相关操作:
        stringRedisTemplate.opsForValue();
        stringRedisTemplate.opsForList();
        stringRedisTemplate.opsForHash();
        stringRedisTemplate.opsForSet();
        stringRedisTemplate.opsForZSet();

redisTemplate和stringRedisTemplate也有类似的操作,这里说一下如何使用redisTemplate操作对象。

    @Test
    public void test02() {
        //查出emlpoyee对象
        Employee employee = employeeMapper.getEmpById(1);
        //默认使用JDK序列化机制,将对象序列化后保存在redis中
        redisTemplate.opsForValue().set("emp-1", employee)
    }

在redis中数据保存如下图:因为redisTemplate底层默认使用了JDK序列化机制,因此存储的都是HEX格式。

SpringBoot2.0整合Redis作为缓存_第2张图片

那么如何使用JSON格式存储数据?

(1)自己手动将对象转为JSON字符串,再存入Redis

(2)配置redisTemplate默认序列化规则:使用GenericJackson2JsonRedisSerializer()序列化方式。

这里选用第二种方式:

@Configuration
public class MyRedisConfig {

    @Bean(name="genericJackson2JsonRedisSerializer")
    public GenericJackson2JsonRedisSerializer genericJackson2JsonRedisSerializer() {
        return new GenericJackson2JsonRedisSerializer();
    }

    @Bean(name = "myRedisTemplate")
    public RedisTemplate myRedisTemplate(RedisConnectionFactory redisConnectionFactory,
                                                         GenericJackson2JsonRedisSerializer ser) throws UnknownHostException {
        RedisTemplate template = new RedisTemplate();
        template.setConnectionFactory(redisConnectionFactory);
        //设置序列化方法
        template.setDefaultSerializer(ser);
        return template;
    }

}

测试:

public class SpringbootCacheApplicationTests {
    @Autowired
    private EmployeeMapper employeeMapper;

    @Qualifier("myRedisTemplate")
    @Autowired
    RedisTemplate myRedisTemplate;

   @Test
    public void test02() {
        Employee employee = employeeMapper.getEmpById(1);   
        myRedisTemplate.opsForValue().set("emp-1", employee);
   }
}

在redis中存储的是JSON格式的数据。

SpringBoot2.0整合Redis作为缓存_第3张图片

第五步:Redis缓存原理

CacheAutoConfiguration加载的缓存配置 类如下:

SpringBoot2.0整合Redis作为缓存_第4张图片

当引入了redis的starter后,org.springframework.boot.autoconfigure.cache.RedisCacheConfiguration就会起作用,并创建出RedisCacheManager, 再有RedisCacheManager再创建出RedisCache;

而默认的org.springframework.boot.autoconfigure.cache.SimpleCacheConfiguration在发现已经有了CacheManager后,它就不会再生效,于是默认的ConcurrentMapCacheManager也不会被创建,ConcurrentMapCache也不会被创建,这样缓存就由默认的ConcurrentMapCache切换成为了RedisCache。

于是当我们使用@Cacheable  、@CacheEvit 、 @CachePut时,就会将数据缓存在redis中。

但是直接缓存的话,数据在redis中存储的不是JSON格式,因为默认的redisTemplate使用的是JDK序列化机制。

因此我们要对redis进行序列化设置。

第六步:序列化设置

SpringBoot 1.X 中自定义序列化器通常是声明一个RedisCacheManager并在其构造中传一个RedisTemplate,
再对RedisTemplate配置自定义序列化器就可达到自定义序列化器的目的。
  

@Configuration
public class MyRedisConfig {

   @Bean(name = "jackson2JsonRedisSerializer")
    public Jackson2JsonRedisSerializer jackson2JsonRedisSerializer() {
        return new Jackson2JsonRedisSerializer(Employee.class);
    }

    @Bean
    public RedisTemplate empRedisTemplate(RedisConnectionFactory redisConnectionFactory,
                                                          Jackson2JsonRedisSerializer jackson2JsonRedisSerializer) throws UnknownHostException {
        RedisTemplate template = new RedisTemplate();
        template.setConnectionFactory(redisConnectionFactory);
        //设置序列化方法
        template.setDefaultSerializer(jackson2JsonRedisSerializer);
        return template;
    }

  @Bean
    public RedisCacheManager empCacheManager(RedisTemplate empRedisTemplate) {
        RedisCacheManager redisCacheManager = new RedisCacheManaegr(empRedisTemplate);
        //使用前缀,默认使用CacheName作为前缀
        redisCacheManager.setUserPrefix(true);
        return redisCacheManager;
    }
}

但是在SpringBoot2.X中发生了一些变化,配置如下就可进行序列化设置:

   @Bean
   public RedisCacheConfiguration redisCacheConfiguration() {
        return RedisCacheConfiguration
                .defaultCacheConfig()
                .serializeKeysWith(
                        RedisSerializationContext
                                .SerializationPair
                                .fromSerializer(new StringRedisSerializer()))
                .serializeValuesWith(
                        RedisSerializationContext
                                .SerializationPair
                                .fromSerializer(new GenericJackson2JsonRedisSerializer()));
    }

测试:

mapper、controller都省略,与上一篇是相同的。https://blog.csdn.net/zhoujian_Liu/article/details/86610271

service层:

   @Cacheable(cacheNames= {"emp"},unless="#result == null") //当结果为空时不缓存
    public Employee getEmp(Integer id) {
        System.out.println("查询【" + id + "】号员工");
        return employeeMapper.getEmpById(id);
    }

SpringBoot2.0整合Redis作为缓存_第5张图片

 

以代码方式调用缓存组件:

  @Autowired
  private RedisCacheManager redisCacheManager;  //springboot创建的RedisCacheManager

  public Employee getEmpById(Integer id) {
        Employee employee = employeeMapper.getEmployee ById(id);

        //采用编码的方式存入缓存
        Cache emp= redisCacheManager.getCache("emp");
        emp.put("emp:1", employee );

        return employee ;
    }

注意:

如果使用Jackson2JsonRedisSerializer在反序列化时会遇到问题,因为没有具体泛型或泛型为Object时,
会将缓存中的数据反序列化为LinkedHashMap,而假如我们需要的是Employee对象,因此就会抛出一个异常。
java.lang.ClassCastException: java.base/java.util.LinkedHashMap cannot be cast to com.springboot.domain.Employeegithub:https://github.com/liuzhoujian/springboot-cache

 

你可能感兴趣的:(SringBoot)