解決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的將會是二進(jìn)制數(shù)據(jù),格式如下:
實際上這并不屬于啥錯誤,將上面的二進(jìn)制轉(zhuǎn)化成String后,其實就是“谷歌”。
但這樣可讀性很差,且占用過多內(nèi)存。
成因分析
省流:由于沒有給自定義序列化方式,所以默認(rèn)采用的是jdk序列化器進(jìn)行序列化,導(dǎo)致最后存入的數(shù)據(jù)是二進(jìn)制。
以下是詳細(xì)分析過程:
這是如何調(diào)用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
當(dāng)沒有自定義序列化方式時,默認(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的源碼中其實規(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這個接口的實現(xiàn)類有下面幾種:
對于key一般使用 StringRedisSerializer ; (key一般是字符串)
而對于value一般使用 GenericJackson2JsonRedisSerializer 。(value可能是復(fù)雜的對象)
2.怎么改?
可以通過【配置類注入容器】來實現(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對象時,指定其泛型為<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>
總結(jié)
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
SpringBoot中dubbo+zookeeper實現(xiàn)分布式開發(fā)的應(yīng)用詳解
這篇文章主要介紹了SpringBoot中dubbo+zookeeper實現(xiàn)分布式開發(fā)的應(yīng)用詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-11-11Eclipse中Properties和yml配置文件注釋亂碼的解決
這篇文章主要介紹了Eclipse中Properties和yml配置文件注釋亂碼的解決,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-10-10idea?maven依賴引入失效無法正常導(dǎo)入依賴問題的解決方法
有時候idea導(dǎo)入一個新項目,或者pom文件修改(新增)了依賴,pom文件和代碼會報紅,提示依賴包不存在,下面這篇文章主要給大家介紹了關(guān)于idea?maven依賴引入失效無法正常導(dǎo)入依賴問題的解決方法,需要的朋友可以參考下2023-04-04