dubbo序列化问题(三)子类覆盖父类字段hession反序列化获取不到
程序员文章站
2022-04-04 09:10:01
...
在进行dubbo开发中遇到一个问题,当是用hession2进行序列化时,子类和父类有相同的字段时,hession2反序列化获取不到该字段数据,如下:
import java.io.Serializable; import java.util.Date; public class User implements Serializable{ /** * */ private static final long serialVersionUID = 1L; private String userId; private String userName; private Date addDate; public String getUserId() { return userId; } public void setUserId(String userId) { this.userId = userId; } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public Date getAddDate() { return addDate; } public void setAddDate(Date addDate) { this.addDate = addDate; } }
import java.util.Date; public class ChildrenUser extends User { /** * */ private static final long serialVersionUID = 1L; private String userId; private Date addDate; public String getUserId() { return userId; } public void setUserId(String userId) { this.userId = userId; } public Date getAddDate() { return addDate; } public void setAddDate(Date addDate) { this.addDate = addDate; } @Override public String toString() { return "ChildrenUser [userId=" + userId + ", addDate=" + addDate + "]"; } }
测试程序如下:
import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.Date; import com.alibaba.com.caucho.hessian.io.Hessian2Input; import com.alibaba.com.caucho.hessian.io.Hessian2Output; import com.pinganwj.clinic.api.demo.domain.ChildrenUser; import com.pinganwj.clinic.api.demo.domain.User; public class TestHessionLite1 { public static void main(String[] args) throws IOException { User user=new ChildrenUser(); user.setAddDate(new Date()); user.setUserId("123"); user.setUserName("呵呵"); byte[] aa=TestHessionLite1.serialize(user); Object mm=TestHessionLite1.deserialize(aa); System.out.println(mm.toString()); } public static byte[] serialize(Object obj) throws IOException{ ByteArrayOutputStream os = new ByteArrayOutputStream(); Hessian2Output ho = new Hessian2Output(os); byte[] cc = null; try { if(obj==null) throw new NullPointerException(); ho.writeObject(obj); ho.flushBuffer(); cc=os.toByteArray(); } catch (Exception e) { e.printStackTrace(); }finally{ ho.close(); } return cc; } public static Object deserialize(byte[] by) throws IOException{ try { if(by==null) throw new NullPointerException(); ByteArrayInputStream is = new ByteArrayInputStream(by); Hessian2Input hi = new Hessian2Input(is); return hi.readObject(); } catch (Exception e) { e.printStackTrace(); } return null; } }
运行该测试程序,输出如下
ChildrenUser [userId=null, addDate=null]
然后我再是用kryo来进行序列化,
import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.Serializable; import java.util.Date; import org.apache.commons.codec.binary.Base64; import com.esotericsoftware.kryo.Kryo; import com.esotericsoftware.kryo.io.Input; import com.esotericsoftware.kryo.io.Output; import com.esotericsoftware.kryo.serializers.JavaSerializer; import com.pinganwj.clinic.api.demo.domain.ChildrenUser; import com.pinganwj.clinic.api.demo.domain.User; public class TestKryo1 { public static void main(String[] args) { User user=new ChildrenUser(); user.setAddDate(new Date()); user.setUserId("123"); user.setUserName("呵呵"); String aa=TestKryo1.serialize(user); Object mm=TestKryo1.deserialize(aa,User.class); System.out.println(mm.toString()); } private static <T extends Serializable> String serialize(T obj) { Kryo kryo = new Kryo(); kryo.setReferences(false); kryo.register(obj.getClass(), new JavaSerializer()); ByteArrayOutputStream baos = new ByteArrayOutputStream(); Output output = new Output(baos); kryo.writeClassAndObject(output, obj); output.flush(); output.close(); byte[] b = baos.toByteArray(); try { baos.flush(); baos.close(); } catch (IOException e) { e.printStackTrace(); } return new String(new Base64().encode(b)); } @SuppressWarnings("unchecked") private static <T extends Serializable> T deserialize(String obj, Class<T> clazz) { Kryo kryo = new Kryo(); kryo.setReferences(false); kryo.register(clazz, new JavaSerializer()); ByteArrayInputStream bais = new ByteArrayInputStream( new Base64().decode(obj)); Input input = new Input(bais); return (T) kryo.readClassAndObject(input); } }
输出结果如下:
ChildrenUser [userId=123, addDate=Fri Aug 25 00:28:45 CST 2017]
输出正确。
这个是hession2的一个坑,经过查看源码Hessian2Input类中的readObjectInstance方法
他将父类的属性都读取了
而每次第一次能读取到值,然后第二次读取就是null,都被覆盖了,所以输出都是null。
所以解决方案就是去掉子类中的字段或者父类中的字段,或者改用kryo等其他序列化方式。