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);
    }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM