dubbo 序列化 问题 属性值 丢失 ArrayList 解决

参考文章:http://blog.csdn.net/wanyanxgf/article/details/6944733

                  http://tianya23.blog.51cto.com/1081650/582256/

这里重点说下解决办法:

由于dubbo采用的序列化和反序列化方案为hessian,但是 hessian 对ArrayList 采用CollectionSerializer类进行 序列化处理,这里 实际代码只会对 ArrayList第一层属性进行处理。

项目中使用PageList 封装类 继承了 ArrayList,并且里面有负责 java对象 PageTools,故 无法转换,属性丢失。

public class PageList<E> extends ArrayList<E> {
    private static final long serialVersionUID = 6110720806295292900L;
    private PagingTools pagingTools;

    public PageList() {
        this.pagingTools = new PagingTools();
    }

    public PageList(Collection<E> c) {
        this(c, (PagingTools)null);
    }

    public PageList(Collection<E> c, PagingTools pageTools) {
        super(c);
        this.pagingTools = pageTools == null?new PagingTools():pageTools;
    }

    public PagingTools getPageTools() {
        return this.pagingTools;
    }

    public void setPageTools(PagingTools pageTools) {
        if(pageTools != null) {
            this.pagingTools = pageTools;
        }

    }
}

  

解决方法: 使用其他 序列化方案  ,这里试了 json ,结果一样。 最终没办法,使用了java原生的序列化。

具体操作:  在 dubbo服务端和客户端 配置 序列化方案

<dubbo:protocol serialization="java"/>

h1. 现象

为一个dubbbo接口新增了一个方法:

  1. {code}  
  2. DomainObject<String> testSer();  
  3.   
  4.   
  5. 实现:  
  6. @Override  
  7.     public DomainObject<String> testSer() {  
  8.         DomainObject<String> result = new DomainObject<String>();  
  9.         result.setAge(10);  
  10.         result.setName("test");  
  11.         result.add("DomainObject1");  
  12.         return result;  
  13.     }  
  14. {code}  


返回值定义如下:

  1. {code}  
  2. public class DomainObject<E> extends ArrayList<E> {  
  3.     private static final long serialVersionUID = -7393642276493435828L;  
  4.     private String name;  
  5.     private int    age;  
  6. }  
  7. {code}  


远程调用:

  1. {code}  
  2. DomainObject<String> result = voucherInfoQueryService.testSer();  
  3. System.out.println(result.getAge());  
  4. System.out.println(result.getName());  
  5. System.out.println(result.get(0));  
  6. {code}  


输出结果:丢失了age和name两个属性的值,而 list内部的值还是存在的

  1. {code}  
  2. 0  
  3. null  
  4. DomainObject1  
  5. {code}  

h1. 问题排查

h4. 使用java自带序列化执行序列化和反序列化, 不会出现属性丢失的问题,怀疑dubbo序列化有特殊处理

h4. dubbo 默认用的序列化协议是hessian2,查看代码

序列化时代码如下:

  1. {code}  
  2. public void writeObject(Object object)  
  3.     throws IOException  
  4.   {  
  5.     if (object == null) {  
  6.       writeNull();  
  7.       return;  
  8.     }  
  9.   
  10.   
  11.     Serializer serializer;  
  12.     ##查找对应的serializer  
  13.     serializer = findSerializerFactory().getSerializer(object.getClass());  
  14.     ##序列化  
  15.     serializer.writeObject(object, this);  
  16.   }  
  17. {code}  


查找serializer:由代码可知,上面的DomainObject对应的serializer是CollectionSerializer

  1. {code}  
  2. public Serializer getSerializer(Class cl)  
  3.     throws HessianProtocolException  
  4.   {  
  5.   ...  
  6.    else if (Collection.class.isAssignableFrom(cl)) {  
  7.       if (_collectionSerializer == null) {  
  8.     _collectionSerializer = new CollectionSerializer();  
  9.    ...  
  10.       }  
  11. {code}  


CollectionSerializer.writeObject

  1. {code}  
  2. public void writeObject(Object obj, AbstractHessianOutput out)  
  3.     throws IOException  
  4.   {  
  5.     ...  
  6.     Iterator iter = list.iterator();  
  7.     while (iter.hasNext()) {  
  8.       Object value = iter.next();  
  9.   
  10.   
  11.       out.writeObject(value);  
  12.     }  
  13.     ...  
  14.   }  
  15. {code}  

所以,属性丢失。

原文地址:https://www.cnblogs.com/hutuchong/p/7170954.html