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

實(shí)際上這并不屬于啥錯(cuò)誤,將上面的二進(jìn)制轉(zhuǎn)化成String后,其實(shí)就是“谷歌”。
但這樣可讀性很差,且占用過多內(nèi)存。
成因分析
省流:由于沒有給自定義序列化方式,所以默認(rèn)采用的是jdk序列化器進(jìn)行序列化,導(dǎo)致最后存入的數(shù)據(jù)是二進(jìn)制。
以下是詳細(xì)分析過程:
這是如何調(diào)用redisTemplate并實(shí)現(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ù)類型為兩個(gè)Object。
RedisTemplate可以接收任意Object作為值寫入Redis

當(dāng)沒有自定義序列化方式時(shí),默認(rèn)會使用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對象轉(zhuǎn)成字節(jié)進(jìn)行存儲,也就是之前看到的二進(jìn)制數(shù)據(jù)。
解決方案
1.改什么?
redisTemplate的源碼中其實(shí)規(guī)定了5種序列化器,其中四種默認(rèn)均為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這個(gè)接口的實(shí)現(xiàn)類有下面幾種:

對于key一般使用 StringRedisSerializer ; (key一般是字符串)
而對于value一般使用 GenericJackson2JsonRedisSerializer 。(value可能是復(fù)雜的對象)
2.怎么改?
可以通過【配置類注入容器】來實(shí)現(xiàn)對序列化器的修改
@Configuration
public class RedisConfig {
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory){
//創(chuàng)建RedisTemplate對象
RedisTemplate<String, Object> template = new RedisTemplate<>();
//設(shè)置連接工廠
template.setConnectionFactory(connectionFactory);
//創(chuàng)建JSON序列化工具
GenericJackson2JsonRedisSerializer jsonRedisSerializer = new GenericJackson2JsonRedisSerializer();
//設(shè)置key的序列化
template.setKeySerializer(RedisSerializer.string());
template.setHashKeySerializer(RedisSerializer.string());
//設(shè)置value的序列化
template.setValueSerializer(jsonRedisSerializer);
template.setHashKeySerializer(jsonRedisSerializer);
//返回
return template;
}
}在注入redisTemplate對象時(shí),指定其泛型為<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.報(bào)錯(cuò)怎么辦?
可能會報(bào)下面的錯(cuò)
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>總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Java利用future及時(shí)獲取多線程運(yùn)行結(jié)果
在Java編程中,有時(shí)候會需要及時(shí)獲取線程的運(yùn)行結(jié)果,本文就通過一個(gè)相關(guān)實(shí)例向大家介紹Java利用future及時(shí)獲取線程運(yùn)行結(jié)果的方法,需要的朋友可以參考。2017-10-10
SpringBoot中dubbo+zookeeper實(shí)現(xiàn)分布式開發(fā)的應(yīng)用詳解
這篇文章主要介紹了SpringBoot中dubbo+zookeeper實(shí)現(xiàn)分布式開發(fā)的應(yīng)用詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-11-11
Eclipse中Properties和yml配置文件注釋亂碼的解決
這篇文章主要介紹了Eclipse中Properties和yml配置文件注釋亂碼的解決,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-10-10
Java利用Guava?Retry實(shí)現(xiàn)重處理
guava-retrying是谷歌的Guava庫的一個(gè)小擴(kuò)展,允許為任意函數(shù)調(diào)用創(chuàng)建可配置的重試策略,比如與正常運(yùn)行時(shí)間不穩(wěn)定的遠(yuǎn)程服務(wù)對話的函數(shù)調(diào)用。本文將利用其實(shí)現(xiàn)重處理,感興趣的可以了解一下2022-08-08
idea?maven依賴引入失效無法正常導(dǎo)入依賴問題的解決方法
有時(shí)候idea導(dǎo)入一個(gè)新項(xiàng)目,或者pom文件修改(新增)了依賴,pom文件和代碼會報(bào)紅,提示依賴包不存在,下面這篇文章主要給大家介紹了關(guān)于idea?maven依賴引入失效無法正常導(dǎo)入依賴問題的解決方法,需要的朋友可以參考下2023-04-04

