SpringBoot使用redisTemplate时报错:Caused by: com.fasterxml.jackson.databind.exc.InvalidTypeIdException

文章讲述了在使用SpringDataRedis的redisTemplate获取Hash数据时遇到的InvalidTypeIdException异常,原因是不同业务系统对同一key使用了不同的序列化策略。提供了两种解决方案:一是修改系统B的序列化配置,但可能影响其他业务;二是重构get方法,使用默认的序列化方式获取String类型的值。作者提到了未尝试过第二种方法。

 在使用 redisTemplate.opsForHash().entries("key");获取键值对的时候报错。完整信息如下:

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[])"{"DeviceId":"696530800153063424","StorageMediumId":"1201912970092589058","StoragePolicyId":"1","PreStorageTime":5,"KeepTime":30,"NvrId":"51010499501319000092","StorageMediumPath":"/data/yyshc010test","StoragePolicySliceTime":120,"StoragePolicySliceType":1,"StorageDay":32,"HotStorageDay":32,"ColdVideoTime":0,"StorageRoom":"SC_YaAn_ZX_001","Switchs":[{"Status":1,"FunctionName":"区块链","FunctionCode":"blockchain","functionParam":{"interval":600}},{"FunctionName":"音频","FunctionCode":"audio","[truncated 265 bytes]; line: 1, column: 765]
	at com.fasterxml.jackson.databind.exc.InvalidTypeIdException.from(InvalidTypeIdException.java:43)
	at com.fasterxml.jackson.databind.DeserializationContext.missingTypeIdException(DeserializationContext.java:1638)
	at com.fasterxml.jackson.databind.DeserializationContext.handleMissingTypeId(DeserializationContext.java:1217)
	at com.fasterxml.jackson.databind.jsontype.impl.TypeDeserializerBase._handleMissingTypeId(TypeDeserializerBase.java:300)
	at com.fasterxml.jackson.databind.jsontype.impl.AsPropertyTypeDeserializer._deserializeTypedUsingDefaultImpl(AsPropertyTypeDeserializer.java:164)
	at com.fasterxml.jackson.databind.jsontype.impl.AsPropertyTypeDeserializer.deserializeTypedFromObject(AsPropertyTypeDeserializer.java:105)
	at com.fasterxml.jackson.databind.jsontype.impl.AsPropertyTypeDeserializer.deserializeTypedFromAny(AsPropertyTypeDeserializer.java:193)
	at com.fasterxml.jackson.databind.deser.std.UntypedObjectDeserializer$Vanilla.deserializeWithType(UntypedObjectDeserializer.java:712)
	at com.fasterxml.jackson.databind.deser.impl.TypeWrappedDeserializer.deserialize(TypeWrappedDeserializer.java:68)
	at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4001)
	at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3079)
	at org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer.deserialize(GenericJackson2JsonRedisSerializer.java:130)
	... 30 common frames omitted

原因是:不同业务系统使用了同一个key,并且两个系统使用了不同的序列化策略。

解决办法1:

修改系统B 配置

@Configuration
public class RedisConfigs {

    @Bean
    public RedisTemplate<String,Object> redisTemplate(RedisConnectionFactory redisConnectionFactory){
        RedisTemplate<String,Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        redisTemplate.setKeySerializer(keySerializer());
        redisTemplate.setHashKeySerializer(keySerializer());
        redisTemplate.setValueSerializer(valueSerializer());
        redisTemplate.setHashValueSerializer(valueSerializer());
        return redisTemplate;
    }
    private RedisSerializer<String> keySerializer() {
        return new StringRedisSerializer();
    }
    private RedisSerializer<Object> valueSerializer() {
        //修改前
        //return new GenericJackson2JsonRedisSerializer();
        //修改后
         return new GenericFastJsonRedisSerializer();
    }
}

这种方法有个弊端,会影响到系统B中其他用到json格式key的业务,故采用方法2

解决办法2:

重构get方法

 /**
     * 通过使用redis默认的序列化获取String类型的值
     *
     * @param key 键
     * @return String类型的值
     */
    public String getStringBySer(String key) {
        try {
            return redisTemplate.execute((RedisCallback<String>) connection -> {
                RedisSerializer<String> serializer = redisTemplate.getStringSerializer();
                byte[] serialize = serializer.serialize(key);
                if (serialize == null) {
                    return null;
                }
                byte[] value = connection.get(serialize);
                return serializer.deserialize(value);
            });
        } catch (Exception e) {
            return null;
        }
    }

(PS:本人没用过此方法)

参考文章:https://blog.csdn.net/carterslam/article/details/119817334

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值