Redis采用Jackson作为value的序列化器,但是对于复杂的泛型实体类如User,不能正常反序列化,而是会反序列化成LinkedHashMap类型
现象
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<version>3.4.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.18.1</version>
</dependency>
Redis缓存数据,使用GenericJackson2JsonRedisSerializer
作为value和hash value的序列化器。
// 将用户信息存入redis
redisTemplate.opsForValue().set(RedisConstants.LOGIN_USER_ID + loginUser.getUser().getId(), loginUser);
// 从redis中获取用户信息
LoginUser loginUser = (LoginUser) redisTemplate.opsForValue().get(RedisConstants.LOGIN_USER_ID + userId);
从redis中获取用户信息时,会报错:LinkedHashMap cannot convert to LoginUser。
分析
Redis采用Jackson作为value的序列化器,但是对于复杂的泛型实体类如User,不能正常反序列化,而是会反序列化成LinkedHashMap类型。
好像是User的createTime和updateTime属性由Date
类型改为LocalDateTime
之后,出现的问题。
解决方式
让objectMapper启用默认类型信息,使得序列化时包含类型信息,反序列化时就能根据类型信息进行类型判断,正确反序列化。
objectMapper = new ObjectMapper();
...
// 类型验证器,在反序列化时验证类型信息的安全性
BasicPolymorphicTypeValidator typeValidator = BasicPolymorphicTypeValidator.builder()
.allowIfBaseType(Object.class)
.build();
// 启用默认类型信息,使得序列化时包含类型信息,反序列化时根据类型信息进行类型判断。否则,反序列化复杂的泛型实体类型时会报错。
objectMapper.activateDefaultTyping(typeValidator, ObjectMapper.DefaultTyping.NON_FINAL,
JsonTypeInfo.As.PROPERTY);
...
GenericJackson2JsonRedisSerializer jackson2JsonRedisSerializer =
new GenericJackson2JsonRedisSerializer(objectMapper);