当前位置:   article > 正文

hession2序列化_hessian2序列化

hessian2序列化

1 引入Hessian依赖

  1. <!--hessian-->
  2. <dependency>
  3. <groupId>com.caucho</groupId>
  4. <artifactId>hessian</artifactId>
  5. <version>4.0.38</version>
  6. </dependency>

2 编写Hessian序列化,反序列化方法,定义实体类 示例

  1. public class HessianSerializerUtil {
  2. public static <T> byte[] serialize(T obj) {
  3. byte[] bytes = null;
  4. // 1、创建字节输出流
  5. ByteArrayOutputStream bos = new ByteArrayOutputStream();
  6. // 2、对字节数组流进行再次封装
  7. // step 1. 定义外部序列化工厂
  8. //ExtSerializerFactory extSerializerFactory = new ExtSerializerFactory();
  9. //extSerializerFactory.addSerializer(java.time.OffsetDateTime.class, new OffsetDateTimeRedisSerializer());
  10. //extSerializerFactory.addDeserializer(java.time.OffsetDateTime.class, new OffsetDateTimeRedisDeserializer());
  11. // step 2. 序列化工厂
  12. //SerializerFactory serializerFactory = new SerializerFactory();
  13. //serializerFactory.addFactory(extSerializerFactory);
  14. HessianOutput hessianOutput = new HessianOutput(bos);
  15. //hessianOutput.setSerializerFactory(serializerFactory);
  16. try {
  17. // 注意,obj 必须实现Serializable接口
  18. hessianOutput.writeObject(obj);
  19. bytes = bos.toByteArray();
  20. } catch (IOException e) {
  21. e.printStackTrace();
  22. }
  23. return bytes;
  24. }
  25. public static <T> T deserialize(byte[] data) {
  26. if (data == null) {
  27. return null;
  28. }
  29. // 1、将字节数组转换成字节输入流
  30. ByteArrayInputStream bis = new ByteArrayInputStream(data);
  31. // step 1. 定义外部序列化工厂
  32. //ExtSerializerFactory extSerializerFactory = new ExtSerializerFactory();
  33. //extSerializerFactory.addSerializer(java.time.OffsetDateTime.class, new OffsetDateTimeRedisSerializer());
  34. //extSerializerFactory.addDeserializer(java.time.OffsetDateTime.class, new OffsetDateTimeRedisDeserializer());
  35. // step 2. 序列化工厂
  36. //SerializerFactory serializerFactory = new SerializerFactory();
  37. //serializerFactory.addFactory(extSerializerFactory);
  38. HessianInput hessianInput = new HessianInput(bis);
  39. //hessianInput.setSerializerFactory(serializerFactory);
  40. Object object = null;
  41. try {
  42. object = hessianInput.readObject();
  43. } catch (IOException e) {
  44. e.printStackTrace();
  45. }
  46. return (T) object;
  47. }
  48. }
  1. package cn.micai.base.io;
  2. import java.io.Serializable;
  3. /**
  4. * 描述:
  5. * <p>
  6. *
  7. * transient使用小结
  8. * 1.一旦变量被transient修饰,变量将不再是对象持久化的一部分,该变量内容在序列化后无法获得访问。
  9. * 2.transient关键字只能修饰变量,而不能修饰方法和类。注意,本地变量是不能被transient关键字修饰的。变量如果是用户自定义类变量,则该类需要实现Serializable接口。
  10. * 3.被transient关键字修饰的变量不再能被序列化,一个静态变量不管是否被transient修饰,均不能被序列化。
  11. *
  12. * @author: 赵新国
  13. * @date: 2018/6/7 12:10
  14. */
  15. public class Employee implements Serializable {
  16. private static final long serialVersionUID = 1L;
  17. private int employeeId;
  18. private String employeeName;
  19. /**
  20. * 使用transient关键字,表示该字段不序列化
  21. */
  22. private transient String department;
  23. public int getEmployeeId() {
  24. return employeeId;
  25. }
  26. public void setEmployeeId(int employeeId) {
  27. this.employeeId = employeeId;
  28. }
  29. public String getEmployeeName() {
  30. return employeeName;
  31. }
  32. public void setEmployeeName(String employeeName) {
  33. this.employeeName = employeeName;
  34. }
  35. public String getDepartment() {
  36. return department;
  37. }
  38. public void setDepartment(String department) {
  39. this.department = department;
  40. }
  41. @Override
  42. public String toString() {
  43. return "Employee{" +
  44. "employeeId=" + employeeId +
  45. ", employeeName='" + employeeName + '\'' +
  46. ", department='" + department + '\'' +
  47. '}';
  48. }
  49. }

 

 

hession 序列化的特点

  •  1.一旦变量被transient修饰,变量将不再是对象持久化的一部分,该变量内容在序列化后无法获得访问。
  •  2.transient关键字只能修饰变量,而不能修饰方法和类。被序列化的类需要实现Serializable接口。
  •  3.一个静态变量不管是否被transient修饰,均不能被序列化
  •  4 final类型变量 不管是否被transient修饰,均可以被序列化。
  • 5 Student类集成Teacher类,Teacher类中有跟Student类型相同且属性名相同的字段name,接下来看代码:
  1. public class Person implements Serializable {
  2. private static final long serialVersionUID = 2l;
  3. private int gender;
  4. public int getGender() {
  5. return gender;
  6. }
  7. public void setGender(int gender) {
  8. this.gender = gender;
  9. }
  10. @Override
  11. public String toString() {
  12. return "Person{" +
  13. "gender='" + gender + '\'' +
  14. '}';
  15. }
  16. }
  17. public class Em extends Person {
  18. private int gender;
  19. public Em() {
  20. }
  21. @Override
  22. public int getGender() {
  23. return gender;
  24. }
  25. @Override
  26. public void setGender(int gender) {
  27. this.gender = gender;
  28. //super.setGender(gender);
  29. }
  30. @Override
  31. public String toString() {
  32. return "Em{" +
  33. "gender=" + gender +
  34. '}';
  35. }
  36. }
  37. 测试类:
  38. public class Set {
  39. public static void main(String[] args) throws Exception{
  40. Em person=new Em();
  41. person.setGender(1);
  42. FileOutputStream fos = new FileOutputStream("tempdata.ser");
  43. Hessian2Output output = new Hessian2Output(fos);
  44. output.writeObject(person);
  45. output.close();
  46. FileInputStream fis = new FileInputStream("tempdata.ser");
  47. Hessian2Input input = new Hessian2Input(fis);
  48. Em p = (Em) input.readObject();
  49. System.out.println(p);
  50. }
  51. }
  52. 输出结果为:
  53. Em{gender=0}

理论上输出的结果应该为“gender=1”,但现在为gender=0,原因如下:

  1. hessian序列化的时候会取出对象的所有自定义属性,相同类型的属性是子类在前父类在后的顺序;
  2. hessian在反序列化的时候,是将对象所有属性取出来,存放在一个map中 key = 属性名 value是反序列类,相同名字的会以子类为准进行反序列化;
  3. 相同名字的属性 在反序列化的是时候,由于子类在父类前面,子类的属性总是会被父类的覆盖,由于java多态属性,在上述例子中父类 student.name = null。

得出结论,两种解决办法

1 使用hessian序列化时,一定要注意子类和父类不能有同名字段

2 在给子类赋值的时候,也给父类赋值。

 @Override
    public void setGender(int gender) {
        this.gender = gender;
        //super.setGender(gender);
    }

 

  • 反序列化的时候  类里多了字段,会初始化成默认值,少了值,会自动忽略。
  • 不须使用serialVersionUID  作为版本标识。

 

 

 

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/喵喵爱编程/article/detail/1011992
推荐阅读
相关标签
  

闽ICP备14008679号