• SpringBoot缓存篇Ⅱ --- 整合Redis以及序列化机制


    一.Redis环境搭建

    系统默认是使用ConcurrentMapCacheManager,然后获取和创建ConcurrentMapCache类型的缓存组件,再将数据保存在ConcurrentMap中

    开发中使用缓存中间件:redis,memcached,ehcache

    1.搭建redis环境

    在linux上安装redis(推荐使用docker)。docker安装redis的技巧:使用国内镜像可以加速下载。

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

    2.使用docker启动redis

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

     3.引入redis的starter

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

    4.配置redis

    spring.redis.host=172.**.**.**

    二.RedisTemplate的使用

    SpringBoot底层整合了spring-data-redis,里面的StringRedisTemplate以及RedisTemplate都已经注入到容器中,使用的时候直接从容器中取出来即可。其中StringRedisTemplate封装了redis对字符串的一些常用操作,RedisTemplate封装了一些对象的常用操作。

    1.StringRedisTemplate的使用

    public void testStringRedis() {
            //redis保存数据
            stringRedisTemplate.opsForValue().append("msg","hello");
    
            //读取数据
            String msg = stringRedisTemplate.opsForValue().get("msg");
            System.out.println(msg);
         //list存储数据 
            stringRedisTemplate.opsForList().leftPush("mylist","1");
            stringRedisTemplate.opsForList().leftPush("mylist","2");
            stringRedisTemplate.opsForList().leftPush("mylist","3");
            String mylist = stringRedisTemplate.opsForList().leftPop("mylist"); //删除并查询最顶层的list数据
            System.out.println(mylist);
        }

    2.RedisTemplate的使用

    public void testRedis() {
            employeeRedisTemplate.opsForValue().set("emp-02",employeeMapper.getEmployeeById(2));
        }

    使用set方法保存查询到的员工对象,执行完毕后发现有错误,这是因为Emp对象没有被序列化,没有序列化的对象是无法存入redis数据库。所以需要Emp实体类实现Serializable接口,将对象序列化再次执行发现有数据存储到数据库中,但是是以序列化的方式存储的。

    这样存储数据是有了,但是存在数据库里很不直观,查询数据的人无法知道自己存了什么数据进去,那么如何解决序列化对象的问题呢?

    redis存取序列化对象的解决方式

    方式一:将数据以json形式保存,将对象转为json,转成json对象后,就会以json的形式存储到数据库中。

    方式二:改变默认的序列化规则,由于默认使用jdk的序列化器,切换使用json的序列化器即可解决序列化问题

    @Configuration
    public class MyRedisConfig {
        @Bean
        public RedisTemplate<Object, Employee> empRedisTemplate(RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {
            RedisTemplate<Object, Employee> template = new RedisTemplate();
            template.setConnectionFactory(redisConnectionFactory);
            Jackson2JsonRedisSerializer<Employee> serializer = new Jackson2JsonRedisSerializer(Employee.class);
            template.setDefaultSerializer(serializer);
            return template;
        }
    }

    使用的时候注入该类,使用这个类来调用set方法即可将Emp对象存到数据库里

    @Autowired
    RedisTemplate<Object, Employee> employeeRedisTemplate;

    public void testRedis() {

    employeeRedisTemplate.opsForValue().set("emp-02",employeeMapper.getEmployeeById(2));
    }

    .测试Redis缓存

    1.默认使用ConcurrentMapCacheManager缓存组件来实际给缓存中存取数据。引入redis的starter之后,容器中保存的是RedisCacheManager,开启debug日志报告,可以搜索已经开启了的 org.springframework.boot.autoconfigure.cache.RedisCacheConfiguration,原来的SimpleCacheConfiguration将不再匹配。

    2.RedisCacheManager帮我们创建RedisCache来作为缓存组件,RedisCache通过操作redis来操作缓存数据,原来的缓存替换为redis缓存,注解配置都一样,区别是缓存的内容都存到配置好的redis数据库了。

    3.默认保存数据k-v都是object,利用序列化保存,所以需要反序列化,将其保存为json

      1)、引入了redis的starter,cacheManager变为RedisCacheManager

      2)、默认创建的RedisCacheManager操作redis的时候使用的是RedisTemplate<Object,Object>

      3)、RedisTemplate<Object,Object>默认使用jdk的序列化机制,所以会乱码

      4)、自定义CacheManager(springboox1.x的版本和这个有区别,这边给出的是2.x的例子)

     //容器会自动检测到这个CacheManager,并替换原来自带的CacheManager
        @Primary //若配置多个缓存管理器需要有一个默认的缓存管理器
        @Bean
        public RedisCacheManager myCacheManager(RedisConnectionFactory redisConnectionFactory){
            RedisSerializer<String> redisSerializer = new StringRedisSerializer();
                    //.entryTtl(Duration.ofHours(1)); // 设置缓存有效期一小时
            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);
    
            // 配置序列化(解决乱码的问题)
            RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
                    .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer))
                    .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer))
                    .disableCachingNullValues();
    
            RedisCacheManager cacheManager = RedisCacheManager.builder(redisConnectionFactory)
                    .cacheDefaults(config)
                    .build();
            return cacheManager;
        }

    注意多个缓存管理器时,若需要引入缓存管理器可以在类注解上@CacheConfig(cacheNames = "emp",cacheManager = "myCacheManager") 配置。

    使用编码的方式进行缓存

    上面讲的都是采用注解的方式进行缓存的,实际生产过程中也可以采用编码的方式进行缓存。

    1) 注入缓存管理器

     @Qualifier("myCacheManager")
        @Autowired
        RedisCacheManager myCacheManager;

    2) 编码缓存

     public Department getDept(Integer id){
            Department department = departmentMapper.getDepartmentById(id);
            Cache dept = myCacheManager.getCache("dept"); //获取某个缓存
            dept.put("dept:1",department);
    
            return departmentMapper.getDepartmentById(id);
        }
  • 相关阅读:
    4. ConcurrentHashMap 锁分段机制
    3. 原子变量-CAS算法
    2. 原子变量
    1. volatale 关键字 -内存可见性
    6.8 全局查询日志
    js实现数字分页
    拆箱和装箱
    string与stringbuilder的区别
    C#之out与ref的共性与区别以及用法
    asp.net操作xml(增删查改)
  • 原文地址:https://www.cnblogs.com/wangxiayun/p/10221695.html
Copyright © 2020-2023  润新知