Java中Redis存儲String類型會有亂碼的問題及解決方案
項目場景:
背景:在java中使用Redis存儲String類型的數(shù)據(jù)時,會出現(xiàn)亂碼。
問題描述:
例如:在java中創(chuàng)建RedisTemplate操作String類型的數(shù)據(jù)存儲時,會出現(xiàn)亂碼,如下代碼,
我寫了一條存儲key為name,值為虎哥的字符串。
然后獲取一下這個key為name的值,打印得到的值
package com.sxy.redis;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.RedisTemplate;
@SpringBootTest
class SpringDataRedisDemoApplicationTests {
@Autowired
private RedisTemplate redisTemplate;
@Test
void contextLoads() {
// 寫入一條String數(shù)據(jù)
redisTemplate.opsForValue().set("name", "虎哥");
// 獲取String數(shù)據(jù)
Object name = redisTemplate.opsForValue().get("name");
System.out.println("name=" + name);
}
}我們可以看到出現(xiàn)了亂碼問題:這里不單單是值出現(xiàn)了亂碼,而且key也有亂碼問題

原因分析:
Redis的序列化分析:
因為SpringDataRedis的功能可以接收任何類型的對象,可以幫我們將java對象轉(zhuǎn)成Redis可處理的字節(jié),所以我們存進(jìn)去的 name和虎哥 都被當(dāng)成了java對象,而redisTemplate的底層,默認(rèn)對這些對象得處理方式就是利用JDK的序列化工具,ObjectOutPutStream
進(jìn)入redisTemplate我們發(fā)現(xiàn)了四個屬性的值都是對應(yīng)的數(shù)據(jù)的序列化

這里我們發(fā)現(xiàn)上面四個屬性的值的,都是下面這個方法定義的默認(rèn)的jdk的序列化器

通過斷點調(diào)試redisTemplate.opsForValue().set("name", "虎哥");我們可以發(fā)現(xiàn),進(jìn)入了JdkSerializationRedisSerializer的類中

最后進(jìn)入了這里,可以看到有ObjectOutputStream來寫對象,這個流的作用就是把java對象轉(zhuǎn)換為字節(jié)進(jìn)行writeObject進(jìn)行寫入

所以我們看到的值就是這樣子的數(shù)據(jù)

缺點:
- 可讀性差
- 內(nèi)存占用較大
解決方案:
我們可以通過修改RedisTemplate的序列化來實現(xiàn)數(shù)據(jù)亂碼問題。
RedisSerializer有一些實現(xiàn)類

這里會有兩個我們需要用到的
- StringRedisSerializer
如果我的key和hash可以是字符串的情況下就用它
- GenericJackson2JsonRedisSerializer
如果我的值是對象就用它
上代碼:
代碼如下,寫了一個配置類注冊Bean對象給spring容器管理
package com.sxy.redis.config;
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.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializer;
@Configuration
public class RedisConfig {
@Bean
public RedisTemplate<String,Object> redisTemplate(RedisConnectionFactory redisConnectionFactory){
// 創(chuàng)建RedisTemplate對象
RedisTemplate<String, Object> template = new RedisTemplate<>();
// 設(shè)置連接工廠
template.setConnectionFactory(redisConnectionFactory);
// 創(chuàng)建JSON序列化工具
GenericJackson2JsonRedisSerializer genericJackson2JsonRedisSerializer = new GenericJackson2JsonRedisSerializer();
// 設(shè)置key的序列化為 = String
template.setKeySerializer(RedisSerializer.string());
template.setHashKeySerializer(RedisSerializer.string());
// 設(shè)置value的序列化為 = GenericJackson2JsonRedisSerializer
template.setValueSerializer(genericJackson2JsonRedisSerializer);
template.setHashValueSerializer(genericJackson2JsonRedisSerializer);
// 返回
return template;
}
}注意:如果這里運行的話會報錯為如下:
Caused by: java.lang.NoClassDefFoundError: com/fasterxml/jackson/core/JsonProcessingException
這是個明顯的錯誤,告訴我們用了如下這個JSON序列化類沒有引入jackson的依賴才報錯
GenericJackson2JsonRedisSerializer genericJackson2JsonRedisSerializer =
new GenericJackson2JsonRedisSerializer();
我們只需要添加如下依賴即可
<!-- Jackson依賴--> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> </dependency>
隨后我們嘗試對其進(jìn)行寫入和讀取數(shù)據(jù),發(fā)現(xiàn)key和value都是正常的顯示

總結(jié):
直接在java中使用RedisTemplate模板進(jìn)行寫入字符串?dāng)?shù)據(jù)時會出現(xiàn),key和value都是亂碼問題,
我們修改了RedisTemplate默認(rèn)的序列化器StringRedisSerializer即可解決此問題。
到此這篇關(guān)于Java中Redis存儲String類型會有亂碼的文章就介紹到這了,更多相關(guān)java redis存儲亂碼內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
idea中將單個java類導(dǎo)出為jar包文件的方法
這篇文章主要給大家介紹了關(guān)于idea中將單個java類導(dǎo)出為jar包文件的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2018-09-09
Java多線程中的ReentrantLock可中斷鎖詳細(xì)解讀
這篇文章主要介紹了Java多線程中的ReentrantLock可中斷鎖詳細(xì)解讀,ReentrantLock中的lockInterruptibly()方法使得線程可以在被阻塞時響應(yīng)中斷,比如一個線程t1通過lockInterruptibly()方法獲取到一個可重入鎖,并執(zhí)行一個長時間的任務(wù),需要的朋友可以參考下2023-12-12
mybaties plus實體類設(shè)置typeHandler不生效的解決
這篇文章主要介紹了mybaties plus實體類設(shè)置typeHandler不生效的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-08-08
Spring-AOP-ProceedingJoinPoint的使用詳解
這篇文章主要介紹了Spring-AOP-ProceedingJoinPoint的使用方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2025-03-03
詳解Spring-Boot集成Spring session并存入redis
這篇文章主要介紹了詳解Spring-Boot集成Spring session并存入redis,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-05-05
Java報錯Java.net.SocketTimeoutException的幾種解決方法
在 Java 網(wǎng)絡(luò)編程中,SocketTimeoutException 通常表示在進(jìn)行網(wǎng)絡(luò)操作時,等待響應(yīng)的時間超過了設(shè)定的超時時間,本文將深入探討 Java.net.SocketTimeoutException 的問題,并為開發(fā)者和環(huán)境配置者提供詳細(xì)的解決方案,需要的朋友可以參考下2024-10-10

