Redis系統學習之自定義RedisTemplate


自定義RedisTemplate

序列化源碼分析

  • 在JAVA程序中看到中文是沒有問題的,但是在Redis客戶端工具,也就是命令行中看見是編碼的
  • image.png
  • 繼續分析源碼
  • 查看RedisTemplate.class
  • 在RedisAutoConfiguration.class中點擊
  • image.png
  • 在上面可以看到序列化支持的
  • image.png
  • 往下稍微滑動一些可以看到,默認采用的是JDK的序列化,因為默認4種都是空的
  • image.png
  • 但是我們一般都是采用JSON來做序列化的,這個時候就需要自己定義序列化了

默認序列化存在的問題

  • 創建測試實體類,User
  • image.png
package co.flower.redis02springboot.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.stereotype.Component;

@Data
@Component
@AllArgsConstructor
@NoArgsConstructor
public class User {

    private String name;

    private int age;

}
測試存儲JSON
/**
     * 測試默認序列化
     */
@Test
public void testSerial() throws JsonProcessingException {
    User user = new User("小姐姐", 18);
    // 使用jackson轉換為字符串,我也沒用過
    String jsonUser = new ObjectMapper().writeValueAsString(user);
    redisTemplate.opsForValue().set("user",jsonUser);
    System.out.println(redisTemplate.opsForValue().get("user"));
}

執行結果
{"name":"小姐姐","age":18}
測試存儲對象User
/**
     * 測試默認序列化
     */
@Test
public void testSerial() throws JsonProcessingException {
    User user = new User("小姐姐", 18);
    // 使用jackson轉換為字符串,我也沒用過
    //        String jsonUser = new ObjectMapper().writeValueAsString(user);
    redisTemplate.opsForValue().set("user",user);
    System.out.println(redisTemplate.opsForValue().get("user"));
}

執行結果
// org.springframework.data.redis.serializer.SerializationException: 
Cannot serialize; nested exception is org.springframework.core.serializer.support.SerializationFailedException:
Failed to serialize object using DefaultSerializer; nested exception is java.lang.IllegalArgumentException: DefaultSerializer requires
a Serializable payload but received an object of type [co.flower.redis02springboot.pojo.User]
at org.springframework.data.redis.serializer.JdkSerializationRedisSerializer.serialize(JdkSerializationRedisSerializer.java:96)

 

  • 提示不能序列化,因為沒有實現Serializable接口,所以不能被JDKSerialzationRedisSerializer序列化
  • 為User實現Serializable接口
  • image.png
  • 再次測試,執行成功
  • 返回結果:User(name=小姐姐, age=18)

自定義RedisTemplate

  • 在java下創建config包,里面創建RedisConfig.java
  • image.png
  • 復制源碼中的代碼進行改動
  • 自己設置序列化方式
  • 設置方法
    • 通過redisTemplate對象進行設置
    • 比如:setKeySerializer
    • image.png
    • 點擊入參
    • image.png
    • 查看實現類,就知道有哪些能設置了
    • image.png
  • 配置類代碼 RedisConfig.java
package co.flower.redis02springboot.config;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnSingleCandidate;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

@Configuration
public class RedisConfig {

    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        RedisTemplate<String, Object> template = new RedisTemplate();
        template.setConnectionFactory(redisConnectionFactory);
        // JSON序列化配置 不需要被,不需要知道具體參數含義 大概知道是做什么的就可以 這個就是采用JSON序列化對象
        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);
        // String的序列化配置
        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
        // 所有的Key通過String序列化
        template.setKeySerializer(stringRedisSerializer);
        template.setHashKeySerializer(stringRedisSerializer);
        // 所有的value通過JSON序列化
        template.setValueSerializer(jackson2JsonRedisSerializer);
        template.setHashValueSerializer(jackson2JsonRedisSerializer);
        // 調用剛才看的序列化源碼中默認的方法,重新設置序列化
        template.afterPropertiesSet();
        return template;
    }

}
采用自定義配置之后,清空數據庫再次測試測試代碼如下
/**
     * 測試自定義序列化
     */
@Test
public void testSerial() throws JsonProcessingException {
    User user = new User("小姐姐", 18);
    // 使用jackson轉換為字符串,我也沒用過
    //        String jsonUser = new ObjectMapper().writeValueAsString(user);
    redisTemplate.getConnectionFactory().getConnection().flushDb();// 清空數據庫
    redisTemplate.opsForValue().set("user",user);
    System.out.println(redisTemplate.opsForValue().get("user"));
}
執行結果: User(name=小姐姐, age=18)
  • 沒有問題,查詢數據庫,直接從客戶端查詢
  • image.png
  • 也沒有問題,OK,nice,開發中如果使用的話,直接拷貝就可以用了!當然是配置類,但是一般開發中不直接在業務中引入redisTemplate,而是編寫一個RedisUtils工具類,來包裝一下默認的,因為使用起來比較麻煩~,我就不照着視屏巧了,好幾百行[捂臉],用的時候直接從公司拿,沒有的話百度一個!

問題AQF:

依賴報錯:

在依賴redis的時候不要指定泛型,不然會報錯

/**
* 我居然直接就指定了泛型 RedisTemplate<String,Object>結果就直接報錯了,刪除泛型后成功
*/
@Autowired
private RedisTemplate redisTemplate;

作者:彼岸舞

時間:2021\05\05

內容關於:Redis

本文屬於作者原創,未經允許,禁止轉發


免責聲明!

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



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