在進行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等其他序列化方式。