參考文章: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接口新增了一個方法:
- {code}
- DomainObject<String> testSer();
- 實現:
- @Override
- public DomainObject<String> testSer() {
- DomainObject<String> result = new DomainObject<String>();
- result.setAge(10);
- result.setName("test");
- result.add("DomainObject1");
- return result;
- }
- {code}
返回值定義如下:
- {code}
- public class DomainObject<E> extends ArrayList<E> {
- private static final long serialVersionUID = -7393642276493435828L;
- private String name;
- private int age;
- }
- {code}
遠程調用:
- {code}
- DomainObject<String> result = voucherInfoQueryService.testSer();
- System.out.println(result.getAge());
- System.out.println(result.getName());
- System.out.println(result.get(0));
- {code}
輸出結果:丟失了age和name兩個屬性的值,而 list內部的值還是存在的
- {code}
- 0
- null
- DomainObject1
- {code}
h1. 問題排查
h4. 使用java自帶序列化執行序列化和反序列化, 不會出現屬性丟失的問題,懷疑dubbo序列化有特殊處理
h4. dubbo 默認用的序列化協議是hessian2,查看代碼
序列化時代碼如下:
- {code}
- public void writeObject(Object object)
- throws IOException
- {
- if (object == null) {
- writeNull();
- return;
- }
- Serializer serializer;
- ##查找對應的serializer
- serializer = findSerializerFactory().getSerializer(object.getClass());
- ##序列化
- serializer.writeObject(object, this);
- }
- {code}
查找serializer:由代碼可知,上面的DomainObject對應的serializer是CollectionSerializer
- {code}
- public Serializer getSerializer(Class cl)
- throws HessianProtocolException
- {
- ...
- else if (Collection.class.isAssignableFrom(cl)) {
- if (_collectionSerializer == null) {
- _collectionSerializer = new CollectionSerializer();
- ...
- }
- {code}
CollectionSerializer.writeObject
- {code}
- public void writeObject(Object obj, AbstractHessianOutput out)
- throws IOException
- {
- ...
- Iterator iter = list.iterator();
- while (iter.hasNext()) {
- Object value = iter.next();
- out.writeObject(value);
- }
- ...
- }
- {code}
所以,屬性丟失。