当前位置: 代码网 > it编程>编程语言>Java > Spring的RedisTemplate的json反序列泛型丢失问题解决

Spring的RedisTemplate的json反序列泛型丢失问题解决

2025年07月19日 Java 我要评论
背景在使用redistemplate操作redis时我们针对对象的序列化通常将序列化成json存储到redis。一般如下配置@bean @conditionalonmissingbean publ

背景

在使用redistemplate操作redis时我们针对对象的序列化通常将序列化成json存储到redis。一般如下配置

@bean  
@conditionalonmissingbean  
public redistemplate<?, ?> redistemplate(redisconnectionfactory redisconnectionfactory,  
                                         objectprovider<redistemplatecustomizer> customizers) {  
    redistemplate<?, ?> redistemplate = new redistemplate<>();  
    redistemplate.setconnectionfactory(redisconnectionfactory);  
  
    stringredisserializer keyserializer = new stringredisserializer();  
    redistemplate.setkeyserializer(keyserializer);  
    redistemplate.sethashkeyserializer(keyserializer);  
  
    objectmapper objectmapper = objectmapperwrapper.getobjectmapper();  
    genericjackson2jsonredisserializer valueserializer = new genericjackson2jsonredisserializer(objectmapper);  
    redistemplate.setvalueserializer(valueserializer);  
    redistemplate.sethashvalueserializer(valueserializer);  
  
    customizers.orderedstream().foreach((customizer) -> customizer.customize(redistemplate));  
    return redistemplate;  
}

使用genericjackson2jsonredisserializer进行配置。但是这种方式会引发一个问题当进行反序列时如果是对象则会报错例如: securityuserinfo o = (securityuserinfo) redistemplateobject.opsforvalue().get(key); 会报linkedhashmap无法转成具体的类型。因为序列化的json没有包含类型信息。只能按照默认的方式转换成linkedhashmap

解决方案

方案一

将jackson库的objectmapper序列化时带上类型信息mapper.activatedefaulttyping(laissezfairesubtypevalidator.instance, objectmapper.defaulttyping.non_final); 但是这种方式会有几个缺点:

  • 增加redis存储,因为带上的类型信息
  • 可读性下降,类型信息会混淆在json中
  • 如果多个应用读写redis会增加理解成本 所以此方案并不推荐

方案二

不使用activatedefaulttyping,查询的时候使用object接收,然后使用mapper.convertvalue方法转换。缺点是多一次序列化的操作,影响性能

方案三

曲线救国,使用scopevalue将类型信息传递给redistemplate的序列化器(也可以用threadlocal),当反序列化时动态获取其类型。这个方式需要增加几个类,使用方式变化一下

  • 增加helper类
import lombok.extern.slf4j.slf4j;  
  
import java.util.concurrent.callable;  
  
/**  
 * @author wxl  
 */@slf4j  
@suppresswarnings("all")  
public class redisdeserializehelper {  
  
    public static final scopedvalue<class<?>> type = scopedvalue.newinstance();  
  
    public static <r> r call(class<r> clazz, callable<object> op) {  
        try {  
            object call = scopedvalue.where(type, clazz).call(op);  
            if (call == null) {  
                return null;  
            }  
            if (clazz.isassignablefrom(call.getclass())) {  
                return (r) call;  
            }  
            return (r) call;  
        } catch (exception e) {  
            log.error("redis deserialize failed", e);  
            throw new runtimeexception(e);  
        }  
    }  
  
    public static class<?> get() {  
        return type.get();  
    }  
}
  • 增加自定义编解码器
import com.fasterxml.jackson.databind.objectmapper;  
import org.springframework.data.redis.serializer.genericjackson2jsonredisserializer;  
import org.springframework.data.redis.serializer.serializationexception;  
  
/**  
 * @author wxl  
 */public class sofastgenericjackson2jsonredisserializer extends genericjackson2jsonredisserializer {  
  
    public sofastgenericjackson2jsonredisserializer(objectmapper objectmapper) {  
        super(objectmapper);  
    }  
  
    @override  
    public object deserialize(byte[] source) throws serializationexception {  
        class<?> clazz = redisdeserializehelper.get();  
        if (clazz != null) {  
            return deserialize(source, clazz);  
        }  
        return super.deserialize(source);  
    }  
  
    @override  
    public <t> t deserialize(byte[] source, class<t> type) throws serializationexception {  
        return super.deserialize(source, type);  
    }  
}
  • 调用方式
securityuserinfo securityuserinfo = redisdeserializehelper.call(securityuserinfo.class, () -> redistemplateobject.opsforvalue().get(key));

总结

  • 如果性能要求不高推荐使用方案二,对性能要求高可以参考方案三
  • 另外对于redisson的序列化也会遇到相同的问题,但是redisson可以再从redis获取值时指定编解码器。所以这个问题影响比较小。

 到此这篇关于spring的redistemplate的json反序列泛型丢失问题解决的文章就介绍到这了,更多相关redistemplate 反序列泛型丢失内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com