网络编程中经常会遇到序列化和反序列化的问题,
序列化就是将Java Object转成byte[];反序列化就是将byte[]转成Java Object。
下面介绍一个序列化和反序列化的工具类,可以绕过构造函数创建Java对象,
Protostuff是一个序列化库,支持以下序列化格式:
- protobuf
- protostuff(本地)
- graph
- json
- smile
- xml
- yaml
- kvp
pom依赖:
<dependency>
<groupId>org.objenesis</groupId>
<artifactId>objenesis</artifactId>
</dependency>
具体源码:
package com.gomeplus.rpc.common.util;
import java.util.HashMap;
import java.util.Map;
import org.objenesis.Objenesis;
import org.objenesis.ObjenesisStd;
import com.dyuproject.protostuff.LinkedBuffer;
import com.dyuproject.protostuff.ProtostuffIOUtil;
import com.dyuproject.protostuff.Schema;
import com.dyuproject.protostuff.runtime.RuntimeSchema;
/**
* 序列化工具类(基于Protostuff实现)
*/
public class SerializationUtil {
private static Map<Class<?>, Schema<?>> cachedSchema = new HashMap<Class<?>, Schema<?>>();
private static Objenesis objenesis = new ObjenesisStd(true);
private SerializationUtil() {
}
/**
* 获取类的schema
* @param cls
* @return
*/
@SuppressWarnings("unchecked")
private static <T> Schema<T> getSchema(Class<T> cls) {
Schema<T> schema = (Schema<T>) cachedSchema.get(cls);
if (schema == null) {
schema = RuntimeSchema.createFrom(cls);
if (schema != null) {
cachedSchema.put(cls, schema);
}
}
return schema;
}
/**
* 序列化(对象 -> 字节数组)
*/
@SuppressWarnings("unchecked")
public static <T> byte[] serialize(T obj) {
Class<T> cls = (Class<T>) obj.getClass();
LinkedBuffer buffer = LinkedBuffer.allocate(LinkedBuffer.DEFAULT_BUFFER_SIZE);
try {
Schema<T> schema = getSchema(cls);
return ProtostuffIOUtil.toByteArray(obj, schema, buffer);//序列化
} catch (Exception e) {
throw new IllegalStateException(e.getMessage(), e);
} finally {
buffer.clear();
}
}
/**
* 反序列化(字节数组 -> 对象)
*/
public static <T> T deserialize(byte[] data, Class<T> cls) {
try {
/*
* 如果一个类没有参数为空的构造方法时候,那么你直接调用newInstance方法试图得到一个实例对象的时候是会抛出异常的
* 通过ObjenesisStd可以完美的避开这个问题
* */
T message = (T) objenesis.newInstance(cls);//实例化
Schema<T> schema = getSchema(cls);//获取类的schema
ProtostuffIOUtil.mergeFrom(data, message, schema);
return message;
} catch (Exception e) {
throw new IllegalStateException(e.getMessage(), e);
}
}
}