SpringBoot使用@Cacheable出現(xiàn)預(yù)覽工具亂碼的解決方法
直接使用注解進(jìn)行緩存數(shù)據(jù),我們再使用工具去預(yù)覽存儲的數(shù)據(jù)時(shí)發(fā)現(xiàn)是亂碼,這是由于默認(rèn)序列化的問題,默認(rèn)是使用JdkSerializationRedisSerializer,我們將其更改即可
解決辦法
我們重新定義一個(gè)org.springframework.data.redis.cache.RedisCacheConfiguration的Bean,并修改序列化器即可
/**
* 此類解決 @Cacheable 存入的緩存使用預(yù)覽工具時(shí)亂碼問題
*
* @author YinShangwen
* @since 2023/10/5 14:02
*/
@Configuration
public class RedisCacheConfig {
@Bean
public RedisCacheConfiguration redisCacheConfiguration(CacheProperties cacheProperties) {
CacheProperties.Redis redisProperties = cacheProperties.getRedis();
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig();
// 工具預(yù)覽亂碼問題
config = config.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericFastJsonRedisSerializer()));
if (redisProperties.getTimeToLive() != null) {
config = config.entryTtl(redisProperties.getTimeToLive());
}
if (redisProperties.getKeyPrefix() != null) {
config = config.prefixCacheNameWith(redisProperties.getKeyPrefix());
}
if (!redisProperties.isCacheNullValues()) {
config = config.disableCachingNullValues();
}
if (!redisProperties.isUseKeyPrefix()) {
config = config.disableKeyPrefix();
}
return config;
}
}??
注意:如果之前有@Cacheable方式存儲的緩存需要清理掉。否則會因?yàn)樾蛄谢?反序列化方式不一致而導(dǎo)致錯(cuò)誤
源碼導(dǎo)讀
RedisCache#put
找到 org.springframework.data.redis.cache.RedisCache#put 方法。這個(gè)方法就是最終存入的方法
/*
* (non-Javadoc)
* @see org.springframework.cache.Cache#put(java.lang.Object, java.lang.Object)
*/
@Override
public void put(Object key, @Nullable Object value) {
Object cacheValue = preProcessCacheValue(value);
if (!isAllowNullValues() && cacheValue == null) {
throw new IllegalArgumentException(String.format(
"Cache '%s' does not allow 'null' values. Avoid storing null via '@Cacheable(unless=\"#result == null\")' or configure RedisCache to allow 'null' via RedisCacheConfiguration.",
name));
}
cacheWriter.put(name, createAndConvertCacheKey(key), serializeCacheValue(cacheValue), cacheConfig.getTtl());
}serializeCacheValue
我們注意到serializeCacheValue(cacheValue)
private final RedisCacheConfiguration cacheConfig;
/**
* Serialize the value to cache.
*
* @param value must not be {@literal null}.
* @return never {@literal null}.
*/
protected byte[] serializeCacheValue(Object value) {
if (isAllowNullValues() && value instanceof NullValue) {
return BINARY_NULL_VALUE;
}
return ByteUtils.getBytes(cacheConfig.getValueSerializationPair().write(value));
}getValueSerializationPair
再看 cacheConfig.getValueSerializationPair() 是什么
private final SerializationPair<Object> valueSerializationPair;
/**
* @return never {@literal null}.
*/
public SerializationPair<Object> getValueSerializationPair() {
return valueSerializationPair;
}這個(gè)變量就是最終決定序列化的類了,如何設(shè)置呢?在RedisCacheConfiguration中有如下方法
/**
* Define the {@link SerializationPair} used for de-/serializing cache values.
*
* @param valueSerializationPair must not be {@literal null}.
* @return new {@link RedisCacheConfiguration}.
*/
public RedisCacheConfiguration serializeValuesWith(SerializationPair<?> valueSerializationPair) {
Assert.notNull(valueSerializationPair, "ValueSerializationPair must not be null!");
return new RedisCacheConfiguration(ttl, cacheNullValues, usePrefix, keyPrefix, keySerializationPair,
valueSerializationPair, conversionService);
}默認(rèn)的RedisCacheConfiguration如何被裝載
找到類org.springframework.boot.autoconfigure.cache.RedisCacheConfiguration
注意:類名相同但包路徑不相同
org.springframework.boot.autoconfigure.cache.RedisCacheConfiguration
org.springframework.data.redis.cache.RedisCacheConfiguration
class RedisCacheConfiguration {
...
private org.springframework.data.redis.cache.RedisCacheConfiguration createConfiguration(
CacheProperties cacheProperties, ClassLoader classLoader) {
Redis redisProperties = cacheProperties.getRedis();
org.springframework.data.redis.cache.RedisCacheConfiguration config = org.springframework.data.redis.cache.RedisCacheConfiguration
.defaultCacheConfig();
// 重點(diǎn)
config = config.serializeValuesWith(
SerializationPair.fromSerializer(new JdkSerializationRedisSerializer(classLoader)));
if (redisProperties.getTimeToLive() != null) {
config = config.entryTtl(redisProperties.getTimeToLive());
}
if (redisProperties.getKeyPrefix() != null) {
config = config.prefixCacheNameWith(redisProperties.getKeyPrefix());
}
if (!redisProperties.isCacheNullValues()) {
config = config.disableCachingNullValues();
}
if (!redisProperties.isUseKeyPrefix()) {
config = config.disableKeyPrefix();
}
return config;
}
}我們只看org.springframework.data.redis.cache.RedisCacheConfiguration是如何創(chuàng)建的所以省略了部分代碼
我們看到默認(rèn)使用的序列化器是 JdkSerializationRedisSerializer
以上就是SpringBoot使用@Cacheable出現(xiàn)預(yù)覽工具亂碼的解決方法的詳細(xì)內(nèi)容,更多關(guān)于SpringBoot使用@Cacheable出現(xiàn)亂碼的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Java簡單實(shí)現(xiàn)農(nóng)夫過河問題示例
這篇文章主要介紹了Java簡單實(shí)現(xiàn)農(nóng)夫過河問題,簡單描述了農(nóng)夫過河問題的概念、原理并結(jié)合簡單實(shí)例形式分析了java解決農(nóng)夫過河問題的相關(guān)操作技巧,需要的朋友可以參考下2017-12-12
Jmeter參數(shù)化獲取序列數(shù)據(jù)實(shí)現(xiàn)過程
這篇文章主要介紹了Jmeter參數(shù)化獲取序列數(shù)據(jù)實(shí)現(xiàn)過程,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-07-07
使用Maven Archetype插件構(gòu)建Maven工程原型模板的實(shí)例
下面小編就為大家分享一篇使用Maven Archetype插件構(gòu)建Maven工程原型模板的實(shí)例,具有很好的參考價(jià)值,希望對大家有所幫助2017-12-12
springboot如何為web層添加統(tǒng)一請求前綴
這篇文章主要介紹了springboot如何為web層添加統(tǒng)一請求前綴,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-02-02
Java長度不足左位補(bǔ)0的3種實(shí)現(xiàn)方法
這篇文章主要介紹了Java長度不足左位補(bǔ)0的3種實(shí)現(xiàn)方法小結(jié),具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-12-12
下載遠(yuǎn)程maven倉庫的jar?手動放到本地倉庫詳細(xì)操作
這篇文章主要介紹了如何下載遠(yuǎn)程maven倉庫的jar?手動放到本地倉庫,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-03-03
實(shí)戰(zhàn)分布式醫(yī)療掛號系統(tǒng)之設(shè)置微服務(wù)接口開發(fā)模塊
這篇文章主要為大家介紹了實(shí)戰(zhàn)分布式醫(yī)療掛號系統(tǒng)之接口開發(fā)醫(yī)院設(shè)置微服務(wù)模塊,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-04-04

