dubbo序列化问题(三)子类覆盖父类字段hession反序列化获取不到

朱雀 2022-04-06 10:46 364阅读 0赞

在进行dubbo开发中遇到一个问题,当是用hession2进行序列化时,子类和父类有相同的字段时,hession2反序列化获取不到该字段数据,如下:

  1. import java.io.Serializable;
  2. import java.util.Date;
  3. public class User implements Serializable{
  4. /**
  5. *
  6. */
  7. private static final long serialVersionUID = 1L;
  8. private String userId;
  9. private String userName;
  10. private Date addDate;
  11. public String getUserId() {
  12. return userId;
  13. }
  14. public void setUserId(String userId) {
  15. this.userId = userId;
  16. }
  17. public String getUserName() {
  18. return userName;
  19. }
  20. public void setUserName(String userName) {
  21. this.userName = userName;
  22. }
  23. public Date getAddDate() {
  24. return addDate;
  25. }
  26. public void setAddDate(Date addDate) {
  27. this.addDate = addDate;
  28. }
  29. }
  30. import java.util.Date;
  31. public class ChildrenUser extends User {
  32. /**
  33. *
  34. */
  35. private static final long serialVersionUID = 1L;
  36. private String userId;
  37. private Date addDate;
  38. public String getUserId() {
  39. return userId;
  40. }
  41. public void setUserId(String userId) {
  42. this.userId = userId;
  43. }
  44. public Date getAddDate() {
  45. return addDate;
  46. }
  47. public void setAddDate(Date addDate) {
  48. this.addDate = addDate;
  49. }
  50. @Override
  51. public String toString() {
  52. return "ChildrenUser [userId=" + userId + ", addDate=" + addDate + "]";
  53. }
  54. }

测试程序如下:

  1. import java.io.ByteArrayInputStream;
  2. import java.io.ByteArrayOutputStream;
  3. import java.io.IOException;
  4. import java.util.Date;
  5. import com.alibaba.com.caucho.hessian.io.Hessian2Input;
  6. import com.alibaba.com.caucho.hessian.io.Hessian2Output;
  7. import com.pinganwj.clinic.api.demo.domain.ChildrenUser;
  8. import com.pinganwj.clinic.api.demo.domain.User;
  9. public class TestHessionLite1 {
  10. public static void main(String[] args) throws IOException {
  11. User user=new ChildrenUser();
  12. user.setAddDate(new Date());
  13. user.setUserId("123");
  14. user.setUserName("呵呵");
  15. byte[] aa=TestHessionLite1.serialize(user);
  16. Object mm=TestHessionLite1.deserialize(aa);
  17. System.out.println(mm.toString());
  18. }
  19. public static byte[] serialize(Object obj) throws IOException{
  20. ByteArrayOutputStream os = new ByteArrayOutputStream();
  21. Hessian2Output ho = new Hessian2Output(os);
  22. byte[] cc = null;
  23. try {
  24. if(obj==null) throw new NullPointerException();
  25. ho.writeObject(obj);
  26. ho.flushBuffer();
  27. cc=os.toByteArray();
  28. } catch (Exception e) {
  29. e.printStackTrace();
  30. }finally{
  31. ho.close();
  32. }
  33. return cc;
  34. }
  35. public static Object deserialize(byte[] by) throws IOException{
  36. try {
  37. if(by==null) throw new NullPointerException();
  38. ByteArrayInputStream is = new ByteArrayInputStream(by);
  39. Hessian2Input hi = new Hessian2Input(is);
  40. return hi.readObject();
  41. } catch (Exception e) {
  42. e.printStackTrace();
  43. }
  44. return null;
  45. }
  46. }

运行该测试程序,输出如下

  1. ChildrenUser [userId=null, addDate=null]

然后我再是用kryo来进行序列化,

  1. import java.io.ByteArrayInputStream;
  2. import java.io.ByteArrayOutputStream;
  3. import java.io.IOException;
  4. import java.io.Serializable;
  5. import java.util.Date;
  6. import org.apache.commons.codec.binary.Base64;
  7. import com.esotericsoftware.kryo.Kryo;
  8. import com.esotericsoftware.kryo.io.Input;
  9. import com.esotericsoftware.kryo.io.Output;
  10. import com.esotericsoftware.kryo.serializers.JavaSerializer;
  11. import com.pinganwj.clinic.api.demo.domain.ChildrenUser;
  12. import com.pinganwj.clinic.api.demo.domain.User;
  13. public class TestKryo1 {
  14. public static void main(String[] args) {
  15. User user=new ChildrenUser();
  16. user.setAddDate(new Date());
  17. user.setUserId("123");
  18. user.setUserName("呵呵");
  19. String aa=TestKryo1.serialize(user);
  20. Object mm=TestKryo1.deserialize(aa,User.class);
  21. System.out.println(mm.toString());
  22. }
  23. private static <T extends Serializable> String serialize(T obj) {
  24. Kryo kryo = new Kryo();
  25. kryo.setReferences(false);
  26. kryo.register(obj.getClass(), new JavaSerializer());
  27. ByteArrayOutputStream baos = new ByteArrayOutputStream();
  28. Output output = new Output(baos);
  29. kryo.writeClassAndObject(output, obj);
  30. output.flush();
  31. output.close();
  32. byte[] b = baos.toByteArray();
  33. try {
  34. baos.flush();
  35. baos.close();
  36. } catch (IOException e) {
  37. e.printStackTrace();
  38. }
  39. return new String(new Base64().encode(b));
  40. }
  41. @SuppressWarnings("unchecked")
  42. private static <T extends Serializable> T deserialize(String obj,
  43. Class<T> clazz) {
  44. Kryo kryo = new Kryo();
  45. kryo.setReferences(false);
  46. kryo.register(clazz, new JavaSerializer());
  47. ByteArrayInputStream bais = new ByteArrayInputStream(
  48. new Base64().decode(obj));
  49. Input input = new Input(bais);
  50. return (T) kryo.readClassAndObject(input);
  51. }
  52. }

输出结果如下:

  1. ChildrenUser [userId=123, addDate=Fri Aug 25 00:28:45 CST 2017]

输出正确。

这个是hession2的一个坑,经过查看源码Hessian2Input类中的readObjectInstance方法

他将父类的属性都读取了

46aa6187-3b55-328e-bc56-c21c7e399abc.png

而每次第一次能读取到值,然后第二次读取就是null,都被覆盖了,所以输出都是null。

所以解决方案就是去掉子类中的字段或者父类中的字段,或者改用kryo等其他序列化方式。

发表评论

表情:
评论列表 (有 0 条评论,364人围观)

还没有评论,来说两句吧...

相关阅读

    相关 序列序列

    序列化: 对象的序列化主要有两种用途:   1) 把对象的字节序列永久地保存到硬盘上,通常存放在一个文件中;   2) 在网络上传送对象的字节序列。