使用了XSTREAM的序列化和反序列化,感觉效果不错。
XSTREAM支持好几种方式的序列化(XML、JSON、BIN),几种方式都有其鲜明的优点:
1)XML方式最容易阅读,且应用范围比较广。
2)JSON方式便于WEB上的传输
3)BIN方式的性能最好,占用的空间也比较少
在反序列化时,由于类的结构发生变化导致一些属性不存在了,可以通过下面的方式对于不存在的属性予以忽略:
private static final XStream DESERIALIZE_XSTREAM = new XStream() {
/**
* 忽略不存在的属性
*/
protected MapperWrapper wrapMapper(MapperWrapper next) {
return new MapperWrapper(next) {
public Class<?> realClass(String elementName) {
try {
return super.realClass(elementName);
} catch (CannotResolveClassException crce) {
return null;
}
}
};
}
};
XSTREAM序列化时会带上类的全路径,比较不好看也占用空间,可以通过别名的方式简化
static {
final DatasetSerializer dsSerializer = new DatasetSerializer();
final DateSerializer dtSerializer = new DateSerializer();
SERIALIZE_XSTREAM.alias("MP", Map.class);
SERIALIZE_XSTREAM.alias("DS", Dataset.class);
SERIALIZE_XSTREAM.alias("ST", String.class);
SERIALIZE_XSTREAM.registerConverter(dsSerializer);
SERIALIZE_XSTREAM.registerConverter(dtSerializer);
SERIALIZE_XSTREAM.setMode(XStream.NO_REFERENCES);
DESERIALIZE_XSTREAM.alias("MP", Map.class);
DESERIALIZE_XSTREAM.alias("DS", Dataset.class);
DESERIALIZE_XSTREAM.alias("ST", String.class);
DESERIALIZE_XSTREAM.registerConverter(dsSerializer);
DESERIALIZE_XSTREAM.registerConverter(dtSerializer);
DESERIALIZE_XSTREAM.setMode(XStream.NO_REFERENCES);
}
使用BIN的方式序列化和反序列化对象:
public static final byte[] serialize(XStream xstream, Object obj, boolean compress) {
ByteArrayOutputStream bos = new ByteArrayOutputStream(4096);
xstream.marshal(obj, new BinaryStreamWriter(bos));
//xstream.marshal(obj, new CompactWriter(new OutputStreamWriter(bos)));
if (compress) {
return compress(bos.toByteArray());
} else {
return bos.toByteArray();
}
}
/**
* 从XML byte数组中反序列化出一个对象
*
* @param bytes
* @return
*/
public static final Object deserialize(byte[] bytes, boolean decompress) {
byte[] newBytes;
if (decompress) {
newBytes = decompress(bytes);
} else {
newBytes = bytes;
}
ByteArrayInputStream bis = new ByteArrayInputStream(newBytes);
BinaryStreamReader bsr = new BinaryStreamReader(bis);
return DESERIALIZE_XSTREAM.unmarshal(bsr);
}
XSTREAM序列化通过反射来获取对象属性值,一方面反射效率相对较慢,另一方面不是所有的属性都需要序列化。可以通过自己实现特定类的序列化来提高效率。
public class DatasetSerializer implements Converter {
@SuppressWarnings("unchecked")
public void marshal(Object obj, HierarchicalStreamWriter writer, MarshallingContext context) {
Dataset ds = (Dataset) obj;
List<Record> records = ds.getRecordList();
if (!CollectionUtil.isEmpty(records)) {
for (Record record : records) {
writer.startNode("RC");
Map<String, Object> map = record.getNewDatasMap();
context.convertAnother(map);
writer.endNode();
}
}
}
@SuppressWarnings("unchecked")
public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {
Dataset ds = new Dataset();
while (reader.hasMoreChildren()) {
reader.moveDown();
Record r = ds.newRecord();
if (reader.hasMoreChildren()) {
Map<String, Object> m = (Map<String, Object>) context.convertAnother(reader, Map.class);
r.setNewDatasMap(m);
}
reader.moveUp();
}
return ds;
}
@SuppressWarnings("unchecked")
public boolean canConvert(Class cls) {
return cls.equals(Dataset.class);
}
}
public class DateSerializer implements Converter {
public void marshal(Object dt, HierarchicalStreamWriter writer, MarshallingContext ctx) {
Date date = (Date) dt;
writer.setValue(String.valueOf(date.getTime()));
}
public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext ctx) {
Long time = Long.valueOf(reader.getValue());
return new Date(time);
}
@SuppressWarnings("unchecked")
public boolean canConvert(Class cls) {
return cls.equals(Date.class);
}
}