美文网首页
Dubbo中Map类型默认的序列化和反序列化

Dubbo中Map类型默认的序列化和反序列化

作者: 换个名字_b5dd | 来源:发表于2022-03-04 12:04 被阅读0次

序列化:
默认使用的hessian序列化中对Map的序列化使用com.alibaba.com.caucho.hessian.io.MapSerializer.
大致逻辑就是除了把map对象的key-value键值对序列化进去,默认还会将class也序列化进去。

@Override
    public void writeObject(Object obj, AbstractHessianOutput out)
            throws IOException {
        if (out.addRef(obj))
            return;

        Map map = (Map) obj;

        Class cl = obj.getClass();

        if (cl.equals(HashMap.class)
                || !_isSendJavaType
                || !(obj instanceof java.io.Serializable))
            out.writeMapBegin(null);
        else
            out.writeMapBegin(obj.getClass().getName());

        Iterator iter = map.entrySet().iterator();
        while (iter.hasNext()) {
            Map.Entry entry = (Map.Entry) iter.next();

            out.writeObject(entry.getKey());
            out.writeObject(entry.getValue());
        }
        out.writeMapEnd();
    }

反序列化:
默认使用的hessian序列化中对Map的反序列化使用com.alibaba.com.caucho.hessian.io.MapDeserializer.
大致分一下两段逻辑:
构造方法中的逻辑:class类型存在无参构造方法时,直接使用对应的构造方法,否则使用HashMap的无参构造器。

private Class _type;
    private Constructor _ctor;

    public MapDeserializer(Class type) {
        if (type == null)
            type = HashMap.class;

        _type = type;

        Constructor[] ctors = type.getConstructors();
        for (int i = 0; i < ctors.length; i++) {
            if (ctors[i].getParameterTypes().length == 0)
                _ctor = ctors[i];
        }

        if (_ctor == null) {
            try {
                _ctor = HashMap.class.getConstructor(new Class[0]);
            } catch (Exception e) {
                throw new IllegalStateException(e);
            }
        }
    }

反序列化逻辑:类型为null或为Map的,直接只用HashMap。类型为SortedMap的,使用TreeMap,否则使用上一步中构造器去new一个实例。然后将键值对反序列化后put到创建的map实例中

@Override
    public Object readMap(AbstractHessianInput in, Class<?> expectKeyType, Class<?> expectValueType) throws IOException {
        Map map;

        if (_type == null)
            map = new HashMap();
        else if (_type.equals(Map.class))
            map = new HashMap();
        else if (_type.equals(SortedMap.class))
            map = new TreeMap();
        else {
            try {
                map = (Map) _ctor.newInstance();
            } catch (Exception e) {
                throw new IOExceptionWrapper(e);
            }
        }
        in.addRef(map);
        doReadMap(in, map, expectKeyType, expectValueType);
        in.readEnd();
        return map;
    }

总结:
1. 所以在返回类型中使用一些没有无参构造器的类作为成员变量或返回值时,实际创建的对象是HashMap,那么就可能会出现赋值时的类型不匹配的错误。
比如:

@Data
public class MapResponse implements Serializable {

    private ImmutableMap immutableMap;
}
/**
     * map序列化测试接口
     **/
    @InnerAPI(path = "/test/map")
    Response<MapResponse> testMap();

直接dubbo调用时,就会出现以下这种错误:


056BA1C3-0D1B-433C-BE85-4E7EEE131A7F.png
  1. 而上面示例通过泛化调用,则不会有问题。因为不存在赋值的步骤,对象类型在服务端序列化之前经过org.apache.dubbo.rpc.filter.GenericFilter中的onResponse处理过,自定义类型会转成待class键值对的HashMap.

相关文章

  • Dubbo中Map类型默认的序列化和反序列化

    序列化:默认使用的hessian序列化中对Map的序列化使用com.alibaba.com.caucho.hess...

  • dubbo源码:dubbo hessian2序列化协议

    [TOC] 1.dubbo hessian2 序列化协议 Dubbo 默认的hessian2序列化协议内部嵌入了H...

  • Flutter 常用功能介绍

    Json序列化和反序列化 首先,默认的JSON.decode是将一个json格式的string 转化成一个Map ...

  • MessageConvert

    简要描述: 响应对象序列化配置,在默认的json序列化规则无法满足我们的需求时,需要自定义序列化规则,以下以Map...

  • Dubbo的RPC

    总结:RPC有三个要素:1,网络通信;2,序列化;3,代理 网络通信 Dubbo默认使用dubbo协议 Dubbo...

  • Java序列化心得(二):自定义序列化

    正如前文《Java序列化心得(一):序列化设计和默认序列化格式的问题》中所提到的,默认序列化方法存在各种各样的问题...

  • Dubbo的通讯方式:NIO+长连接

    Dubbo默认使用长连接。 Dubbo序列化默认使用的是修改过的Hessian协议,这是一种高效的二进制协议。He...

  • python序列化与反序列化

    json序列化与反序列化 序列化:dumps()/dump(),将python中字典类型的对象序列化后,转化成js...

  • 序列化和反序列细节处理

    python 中pickle 和 json 都是序列化和反序列化的模块。 关于序列化和反序列化 序列化和反序列化[...

  • JAVA反序列化漏洞

    目录 反序列化漏洞序列化和反序列化JAVA WEB中的序列化和反序列化对象序列化和反序列范例JAVA中执行系统命令...

网友评论

      本文标题:Dubbo中Map类型默认的序列化和反序列化

      本文链接:https://www.haomeiwen.com/subject/faaprrtx.html