java中使用RedisTemplate读取数据异常 Missing type id when trying to resolve subtype of [simple type, class java.lang.Object]: missing type id property '@class' at [Source: (byte[])"

java中使用RedisTemplate读取数据异常 Missing type id when trying to resolve subtype of [simple type, class java.lang.Object]: missing type id property '@class' at [Source: (byte[])"

报错:

Caused by: com.fasterxml.jackson.databind.exc.InvalidTypeIdException: Missing type id when trying to resolve subtype of [simple type, class java.lang.Object]: missing type id property '@class'
 at [Source: (byte[])"{"name":"测试","phone":"123","idCard":"12345","channelCode":"0"}"; line: 1, column: 66]

原代码:

@Autowired
private RedisTemplate<String, String> redisTemplate;
redisTemplate.opsForValue().set(token, JSONUtil.toJsonStr(currentUserInfo), tokenExpireTime, TimeUnit.SECONDS);
String userInfoRaw = redisTemplate.opsForValue().get(token);         

错误原因:

redis存储对象时会多存一个@class,用于标注对象属性,再次读取时根据@class来反序列化对象。
但我调用redis存储时用了hutool的JSONUtil.toJsonStr来序列化对象,这个工具类在把对象转化为json字符串时会丢失@class信息,造成redis可以存储,不能读取的bug。

解决方法:

直接储存对象,让redis自己来序列化。
或者使用能保留@class信息的工具来序列化对象。
或者在读取时以字符串/map形式读取,再自己解析一下。

修改后代码:

@Autowired
private RedisTemplate<String, Object> redisTemplate;
redisTemplate.opsForValue().set(token, currentUserInfo, tokenExpireTime, TimeUnit.SECONDS);
Object userInfoRaw = redisTemplate.opsForValue().get(token);         

再存一下解决redis中localDateTime类型参数反序列化错误的方法

@Configuration
public class RedisConfig {
    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.activateDefaultTyping(objectMapper.getPolymorphicTypeValidator(), ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
        // LocalDatetime序列化
        JavaTimeModule timeModule = new JavaTimeModule();
        timeModule.addDeserializer(LocalDate.class,
                new LocalDateDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
        timeModule.addDeserializer(LocalDateTime.class,
                new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        timeModule.addSerializer(LocalDate.class,
                new LocalDateSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
        timeModule.addSerializer(LocalDateTime.class,
                new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
        objectMapper.registerModule(timeModule);
        // 设置键key的序列化方式
        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
        redisTemplate.setKeySerializer(stringRedisSerializer);
        redisTemplate.setHashKeySerializer(stringRedisSerializer);
        // 设置值value的序列化方式
        GenericJackson2JsonRedisSerializer genericJackson2JsonRedisSerializer = new GenericJackson2JsonRedisSerializer(objectMapper);
        redisTemplate.setValueSerializer(genericJackson2JsonRedisSerializer);
        redisTemplate.setHashValueSerializer(genericJackson2JsonRedisSerializer);
        redisTemplate.afterPropertiesSet();
        return redisTemplate;
    }
} 

posted @ 2023-04-25 10:30  一语子  阅读(3194)  评论(0)    收藏  举报