hession2序列化

Posted xiaoliuliu2050

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了hession2序列化相关的知识,希望对你有一定的参考价值。

1 引入Hessian依赖

<!--hessian-->
    <dependency>
      <groupId>com.caucho</groupId>
      <artifactId>hessian</artifactId>
      <version>4.0.38</version>
    </dependency>

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

public class HessianSerializerUtil 

    public static <T> byte[] serialize(T obj) 
        byte[] bytes = null;
        // 1、创建字节输出流
        ByteArrayOutputStream bos = new ByteArrayOutputStream();

        // 2、对字节数组流进行再次封装

        // step 1. 定义外部序列化工厂
        //ExtSerializerFactory extSerializerFactory = new ExtSerializerFactory();
        //extSerializerFactory.addSerializer(java.time.OffsetDateTime.class, new OffsetDateTimeRedisSerializer());
        //extSerializerFactory.addDeserializer(java.time.OffsetDateTime.class, new OffsetDateTimeRedisDeserializer());
        // step 2. 序列化工厂
        //SerializerFactory serializerFactory = new SerializerFactory();
        //serializerFactory.addFactory(extSerializerFactory);

        HessianOutput hessianOutput = new HessianOutput(bos);
        //hessianOutput.setSerializerFactory(serializerFactory);

        try 
            // 注意,obj 必须实现Serializable接口
            hessianOutput.writeObject(obj);
            bytes = bos.toByteArray();
         catch (IOException e) 
            e.printStackTrace();
        

        return bytes;
    

    public static <T> T deserialize(byte[] data) 
        if (data == null) 
            return null;
        
        // 1、将字节数组转换成字节输入流
        ByteArrayInputStream bis = new ByteArrayInputStream(data);

        // step 1. 定义外部序列化工厂
        //ExtSerializerFactory extSerializerFactory = new ExtSerializerFactory();
        //extSerializerFactory.addSerializer(java.time.OffsetDateTime.class, new OffsetDateTimeRedisSerializer());
        //extSerializerFactory.addDeserializer(java.time.OffsetDateTime.class, new OffsetDateTimeRedisDeserializer());
        // step 2. 序列化工厂
        //SerializerFactory serializerFactory = new SerializerFactory();
        //serializerFactory.addFactory(extSerializerFactory);
        HessianInput hessianInput = new HessianInput(bis);
        //hessianInput.setSerializerFactory(serializerFactory);
        Object object = null;

        try 
            object = hessianInput.readObject();
         catch (IOException e) 
            e.printStackTrace();
        

        return (T) object;
    
package cn.micai.base.io;
 
import java.io.Serializable;
 
/**
 * 描述:
 * <p>
 *
 *     transient使用小结
 *     1.一旦变量被transient修饰,变量将不再是对象持久化的一部分,该变量内容在序列化后无法获得访问。
 *     2.transient关键字只能修饰变量,而不能修饰方法和类。注意,本地变量是不能被transient关键字修饰的。变量如果是用户自定义类变量,则该类需要实现Serializable接口。
 *     3.被transient关键字修饰的变量不再能被序列化,一个静态变量不管是否被transient修饰,均不能被序列化。
 *
 * @author: 赵新国
 * @date: 2018/6/7 12:10
 */
public class Employee implements Serializable 
 
    private static final long serialVersionUID = 1L;
    private int employeeId;
    private String employeeName;
    /**
     * 使用transient关键字,表示该字段不序列化
     */
    private transient String department;
 
    public int getEmployeeId() 
        return employeeId;
    
    public void setEmployeeId(int employeeId) 
        this.employeeId = employeeId;
    
    public String getEmployeeName() 
        return employeeName;
    
    public void setEmployeeName(String employeeName) 
        this.employeeName = employeeName;
    
    public String getDepartment() 
        return department;
    
    public void setDepartment(String department) 
        this.department = department;
    
 
    @Override
    public String toString() 
        return "Employee" +
                "employeeId=" + employeeId +
                ", employeeName='" + employeeName + '\\'' +
                ", department='" + department + '\\'' +
                '';
    

 

 

hession 序列化的特点

  •  1.一旦变量被transient修饰,变量将不再是对象持久化的一部分,该变量内容在序列化后无法获得访问。
  •  2.transient关键字只能修饰变量,而不能修饰方法和类。被序列化的类需要实现Serializable接口。
  •  3.一个静态变量不管是否被transient修饰,均不能被序列化
  •  4 final类型变量 不管是否被transient修饰,均可以被序列化。
  • 5 Student类集成Teacher类,Teacher类中有跟Student类型相同且属性名相同的字段name,接下来看代码:
public class Person implements Serializable 
    private static final long serialVersionUID = 2l;
    private  int gender;

    public int getGender() 
        return gender;
    

    public void setGender(int gender) 
        this.gender = gender;
    

    @Override
    public String toString() 
        return "Person" +
                "gender='" + gender + '\\'' +
                '';
    


public class Em extends Person 

    private int gender;

    public Em() 
    

    @Override
    public int getGender() 
        return gender;
    

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

    @Override
    public String toString() 
        return "Em" +
                "gender=" + gender +
                '';
    




测试类:
   public class Set 

    public static void main(String[] args) throws Exception

        Em person=new Em();
        person.setGender(1);


        FileOutputStream fos = new FileOutputStream("tempdata.ser");
        Hessian2Output output = new Hessian2Output(fos);
        output.writeObject(person);
        output.close();


        FileInputStream fis = new FileInputStream("tempdata.ser");
        Hessian2Input input = new Hessian2Input(fis);


        Em p = (Em) input.readObject();
        System.out.println(p);





    


输出结果为:
Emgender=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  作为版本标识。

 

 

 

 

以上是关于hession2序列化的主要内容,如果未能解决你的问题,请参考以下文章

Django 测试客户端不会自动序列化工厂

C++ 模板工厂构造函数/反序列化

如何使用 GWT 序列化流工厂

没有从字符串值('1074')反序列化的字符串参数构造函数/工厂方法

没有从字符串值反序列化的字符串参数构造函数/工厂方法('2018-12-14')

JAVA设计模式 3创建型理解工厂模式与抽象工厂模式