SpringBoot結合Redis實現序列化的方法詳解
前言
最近在學習Spring Boot結合Redis時看了一些網上的教程,發(fā)現這些教程要么比較老,要么不知道從哪抄得,運行起來有問題。這里分享一下我最新學到的寫法
默認情況下,Spring 為我們提供了一個 RedisTemplate 來進行對 Redis 的操作,但是 RedisTemplate 默認配置的是使用Java本機序列化。
這種序列化方式,對于操作字符串或數字來說,用起來還行,但是如果要對對象操作,就不是那么的方便了。
所以我們需要配置合適的序列化方式。在 Spring 官方的文檔中,官方也建議了我們使用其他的方式來進行序列化。比如JSON

https://docs.spring.io/spring-data/redis/docs/2.2.5.RELEASE/reference/html/#redis:serializer
配置類
配置 Jackson2JsonRedisSerializer 序列化策略
下面就開始自動配置類的書寫
我使用的是 Jackson2JsonRedisSerializer 來對對象進行序列化,所以首先需要一個方法,來配置 Jackson2JsonRedisSerializer 序列化策略
private Jackson2JsonRedisSerializer<Object> serializer() {
// 使用Jackson2JsonRedisSerializer來序列化和反序列化redis的value值
Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
ObjectMapper objectMapper = new ObjectMapper();
// 指定要序列化的域,field,get和set,以及修飾符范圍,ANY是都有包括private和public
objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
// 指定序列化輸入的類型,類必須是非final修飾的,final修飾的類,比如String,Integer等會跑出異常
objectMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(objectMapper);
return jackson2JsonRedisSerializer;
}這里要注意的是
objectMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL);
這一句,這一句非常的重要,作用是序列化時將對象全類名一起保存下來
設置之后的序列化結果如下:
[
"com.buguagaoshu.redis.model.User",
{
"name": "1",
"age": "11",
"message": "牛逼"
}
]
不設置的話,序列化結果如下,將無法反序列化
{
"name": "1",
"age": "11",
"message": "牛逼"
}
一開始,我在網上搜了一下,發(fā)現大多數教程因為時間的原因,這一句用的是
objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
但當我把這段代碼寫入的時候,發(fā)現Idea提示我

著是一個過時的方法,由于我當時并不知道這句話的意思,就把這段代碼注釋了,覺得可能沒什么用,但注釋后在向Redis里寫數據的時候,數據會變成


導致數據無法反序列化。
最后我查看了這個方法的源碼,找到了


通過注釋,我得到了這段代碼的最新寫法。
也明白了這段代碼的作用。
配置 RedisTemplate
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(redisConnectionFactory);
// 用Jackson2JsonRedisSerializer來序列化和反序列化redis的value值
redisTemplate.setValueSerializer(serializer());
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
// 使用StringRedisSerializer來序列化和反序列化redis的key值
redisTemplate.setKeySerializer(stringRedisSerializer);
// hash的key也采用String的序列化方式
redisTemplate.setHashKeySerializer(stringRedisSerializer);
// hash的value序列化方式采用jackson
redisTemplate.setHashValueSerializer(serializer());
redisTemplate.afterPropertiesSet();
return redisTemplate;
}這里就沒有什么需要注意的了,按照自己的需求,來配置序列化的方式
配置緩存策略
@Bean
public CacheManager cacheManager(RedisConnectionFactory factory) {
RedisSerializer<String> redisSerializer = new StringRedisSerializer();
// 配置序列化(解決亂碼的問題)
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
// 緩存有效期
.entryTtl(timeToLive)
// 使用StringRedisSerializer來序列化和反序列化redis的key值
.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer))
// 使用Jackson2JsonRedisSerializer來序列化和反序列化redis的value值
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(serializer()))
// 禁用空值
.disableCachingNullValues();
return RedisCacheManager.builder(factory)
.cacheDefaults(config)
.build();
}測試代碼
@SpringBootTest
public class RedisApplicationTests {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
@Test
void contextLoads() throws Exception {
User user = new User();
user.setName("15");
user.setAge(20);
user.setMessage("牛逼");
redisTemplate.opsForValue().set(user.getName(), user);
User getUser = (User) redisTemplate.opsForValue().get(user.getName());
System.out.println(getUser);
System.out.println(getUser.getMessage());
}
}再來查看Redis中的數據

數據正常,并且系統(tǒng)也能正常的反序列化了。
完整代碼
package com.buguagaoshu.redis.config;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import java.time.Duration;
/**
* @author Pu Zhiwei {@literal puzhiweipuzhiwei@foxmail.com}
* create 2020-03-17 21:08
* 繼承 CachingConfigurerSupport,為了自定義生成 KEY 的策略??梢圆焕^承。
*/
@Configuration
@EnableCaching
public class RedisConfig extends CachingConfigurerSupport {
@Value("${spring.cache.redis.time-to-live}")
private Duration timeToLive = Duration.ZERO;
/**
* 配置Jackson2JsonRedisSerializer序列化策略
* */
private Jackson2JsonRedisSerializer<Object> serializer() {
// 使用Jackson2JsonRedisSerializer來序列化和反序列化redis的value值
Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
ObjectMapper objectMapper = new ObjectMapper();
// 指定要序列化的域,field,get和set,以及修飾符范圍,ANY是都有包括private和public
objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
// 指定序列化輸入的類型,類必須是非final修飾的,final修飾的類,比如String,Integer等會跑出異常
objectMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(objectMapper);
return jackson2JsonRedisSerializer;
}
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(redisConnectionFactory);
// 用Jackson2JsonRedisSerializer來序列化和反序列化redis的value值
redisTemplate.setValueSerializer(serializer());
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
// 使用StringRedisSerializer來序列化和反序列化redis的key值
redisTemplate.setKeySerializer(stringRedisSerializer);
// hash的key也采用String的序列化方式
redisTemplate.setHashKeySerializer(stringRedisSerializer);
// hash的value序列化方式采用jackson
redisTemplate.setHashValueSerializer(serializer());
redisTemplate.afterPropertiesSet();
return redisTemplate;
}
@Bean
public CacheManager cacheManager(RedisConnectionFactory factory) {
RedisSerializer<String> redisSerializer = new StringRedisSerializer();
// 配置序列化(解決亂碼的問題)
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
// 緩存有效期
.entryTtl(timeToLive)
// 使用StringRedisSerializer來序列化和反序列化redis的key值
.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer))
// 使用Jackson2JsonRedisSerializer來序列化和反序列化redis的value值
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(serializer()))
// 禁用空值
.disableCachingNullValues();
return RedisCacheManager.builder(factory)
.cacheDefaults(config)
.build();
}
}以上就是SpringBoot結合Redis實現序列化的方法詳解的詳細內容,更多關于SpringBoot Redis序列化的資料請關注腳本之家其它相關文章!
相關文章
Spring Boot插件spring tool suite安裝及使用詳解
這篇文章主要介紹了Spring Boot插件spring tool suite安裝及使用詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2019-08-08
spring @Cacheable擴展實現緩存自動過期時間及自動刷新功能
用過spring cache的朋友應該會知道,Spring Cache默認是不支持在@Cacheable上添加過期時間的,雖然可以通過配置緩存容器時統(tǒng)一指定,本文主要介紹了如何基于spring @Cacheable擴展實現緩存自動過期時間以及緩存即將到期自動刷新,2024-02-02
IDEA2020.1使用LeetCode插件運行并調試本地樣例的方法詳解
這篇文章主要介紹了IDEA2020.1使用LeetCode插件運行并調試本地樣例的方法,本文通過圖文并茂的形式給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友參考下吧2020-09-09

