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,原因如下:
- hessian序列化的时候会取出对象的所有自定义属性,相同类型的属性是子类在前父类在后的顺序;
- hessian在反序列化的时候,是将对象所有属性取出来,存放在一个map中 key = 属性名 value是反序列类,相同名字的会以子类为准进行反序列化;
- 相同名字的属性 在反序列化的是时候,由于子类在父类前面,子类的属性总是会被父类的覆盖,由于java多态属性,在上述例子中父类 student.name = null。
得出结论,两种解决办法
1 使用hessian序列化时,一定要注意子类和父类不能有同名字段
2 在给子类赋值的时候,也给父类赋值。
@Override
public void setGender(int gender)
this.gender = gender;
//super.setGender(gender);
- 反序列化的时候 类里多了字段,会初始化成默认值,少了值,会自动忽略。
- 不须使用serialVersionUID 作为版本标识。
以上是关于hession2序列化的主要内容,如果未能解决你的问题,请参考以下文章
没有从字符串值('1074')反序列化的字符串参数构造函数/工厂方法