解決redisTemplate向redis中插入String類型數(shù)據(jù)時出現(xiàn)亂碼問題
前置知識
1.啥是redisTemplate?
redisTemplate是SpringDataRedis中的一個工具類,封裝了各種對Redis的操作,并將不同數(shù)據(jù)類型的操作API封裝到了不同的類型中
舉例:
下面的語句表示將【"name","谷歌"】這個k-v存入到redis中
redisTemplate.opsForValue().set("name","谷歌");2.啥是序列化和反序列化?
序列化:將對象存入一個文件的過程。
反序列化:從一個文件中解析出對象。
問題描述
首先,這是一個Springboot+SpringDataRedis的項目
如果按照【前置知識】的例子中那樣寫,那么存入redis的將會是二進制數(shù)據(jù),格式如下:

實際上這并不屬于啥錯誤,將上面的二進制轉化成String后,其實就是“谷歌”。
但這樣可讀性很差,且占用過多內存。
成因分析
省流:由于沒有給自定義序列化方式,所以默認采用的是jdk序列化器進行序列化,導致最后存入的數(shù)據(jù)是二進制。
以下是詳細分析過程:
這是如何調用redisTemplate并實現(xiàn)插入數(shù)據(jù)的一段代碼:
@SpringBootTest
class SpringDataRedisDemoApplicationTests {
@Resource
private RedisTemplate redisTemplate;
@Test
void testString() {
// 寫入String數(shù)據(jù)
redisTemplate.opsForValue().set("name","谷歌");
}
}其中set方法的入?yún)?shù)據(jù)類型為兩個Object。
RedisTemplate可以接收任意Object作為值寫入Redis

當沒有自定義序列化方式時,默認會使用jdk序列化器,redisTemplate的源碼中做了下面的定義:
public class RedisTemplate<K, V> extends RedisAccessor implements RedisOperations<K, V>, BeanClassLoaderAware {
@Override
public void afterPropertiesSet() {
...
if (defaultSerializer == null) {
defaultSerializer = new JdkSerializationRedisSerializer(
classLoader != null ? classLoader : this.getClass().getClassLoader());
}
...
}
}
jdk序列化器在底層會將Java對象轉成字節(jié)進行存儲,也就是之前看到的二進制數(shù)據(jù)。
解決方案
1.改什么?
redisTemplate的源碼中其實規(guī)定了5種序列化器,其中四種默認均為null。
public class RedisTemplate<K, V> extends RedisAccessor implements RedisOperations<K, V>, BeanClassLoaderAware {
private @Nullable RedisSerializer<?> defaultSerializer;
private @Nullable RedisSerializer keySerializer = null;
private @Nullable RedisSerializer valueSerializer = null;
private @Nullable RedisSerializer hashKeySerializer = null;
private @Nullable RedisSerializer hashValueSerializer = null;
}那么只要能改變序列化的方式,就能改變存入redis的數(shù)據(jù)類型。
RedisSerializer這個接口的實現(xiàn)類有下面幾種:

對于key一般使用 StringRedisSerializer ; (key一般是字符串)
而對于value一般使用 GenericJackson2JsonRedisSerializer 。(value可能是復雜的對象)
2.怎么改?
可以通過【配置類注入容器】來實現(xiàn)對序列化器的修改
@Configuration
public class RedisConfig {
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory){
//創(chuàng)建RedisTemplate對象
RedisTemplate<String, Object> template = new RedisTemplate<>();
//設置連接工廠
template.setConnectionFactory(connectionFactory);
//創(chuàng)建JSON序列化工具
GenericJackson2JsonRedisSerializer jsonRedisSerializer = new GenericJackson2JsonRedisSerializer();
//設置key的序列化
template.setKeySerializer(RedisSerializer.string());
template.setHashKeySerializer(RedisSerializer.string());
//設置value的序列化
template.setValueSerializer(jsonRedisSerializer);
template.setHashKeySerializer(jsonRedisSerializer);
//返回
return template;
}
}在注入redisTemplate對象時,指定其泛型為<String,Object>
@SpringBootTest
class SpringDataRedisDemoApplicationTests {
@Autowired
private RedisTemplate<String,Object> redisTemplate;
@Test
void testString() {
// 寫入String數(shù)據(jù)
redisTemplate.opsForValue().set("name","百度");
// 獲取String數(shù)據(jù)
Object name = redisTemplate.opsForValue().get("name");
System.out.println(name);
}
}3.報錯怎么辦?
可能會報下面的錯
Caused by: java.lang.NoClassDefFoundError: com/fasterxml/jackson/databind/jsontype/impl/StdTypeResolverBuilder
at stu.demo.springdataredisdemo.config.RedisConfig.redisTemplate(RedisConfig.java:20)
引入下面的依賴即可
<!--Jackson-->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>總結
以上為個人經驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
MyBatisPlus-QueryWrapper多條件查詢及修改方式
這篇文章主要介紹了MyBatisPlus-QueryWrapper多條件查詢及修改方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-06-06
spring boot異步(Async)任務調度實現(xiàn)方法
在沒有使用spring boot之前,我們的做法是在配置文件中定義一個任務池,然后將@Async注解的任務丟到任務池中去執(zhí)行,那么在spring boot中,怎么來實現(xiàn)異步任務的調用了,下面通過本文給大家講解,需要的朋友參考下2018-02-02

