Protostuff 序列化/反序列化工具类:支持序列化/反序列化数组、集合等对象

最近在做SSH项目应用层缓存(redis+protobuf)时,遇到一个超级蛋疼的问题,Protostuff居然不支持序列化/反序列化数组、集合等对象,版本1.5.9。开始以为版本问题,升级到最新版1.6.0,仍然不能解决问题,最后参考网友butioy的解决方案:https://blog.csdn.net/butioy_org/article/details/78412395

重新修改了工具类解决了问题,使用到的技术点:线程隔离可重用buffer缓冲区,泛型返回值,智能处理传参,使支持primitive数组,List,Set,Map实例对象的序列化和反序列化。

附上我的Protostuff 序列化/反序列化工具类java源码:

package framework.webapp.commons.utils;
import io.protostuff.LinkedBuffer;
import io.protostuff.ProtostuffIOUtil;
import io.protostuff.Schema;
import io.protostuff.runtime.RuntimeSchema;
import java.util.Collection;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * **************************************************
 * @description Protostuff 序列化/反序列化工具类
 * @author [email protected]
 * @version 2.0, 2018-08-07
 * @see HISTORY
 *      Date        Desc          Author      Operation
 *  	2017-4-7 创建文件 karl create Date Desc
 * Author Operation 2018-08-07 创建文件 karl Protostuff 不支持序列化/反序列化数组、集合等对象,特殊处理
 * @since 2017 Phyrose Science & Technology (Kunming) Co., Ltd.
 **************************************************/
public class SerializationUtil {

    private static final Log log = LogFactory.getLog(SerializationUtil.class);
    /**
     * 线程局部变量
     */
    private static final ThreadLocal BUFFERS = new ThreadLocal();

    /**
     * 序列化/反序列化包装类 Schema 对象
     */
    private static final Schema WRAPPER_SCHEMA = RuntimeSchema.getSchema(SerializeDeserializeWrapper.class);


    /**
     * 序列化对象
     *
     * @param obj 需要序列化的对象
     * @return 序列化后的二进制数组
     */
    @SuppressWarnings("unchecked")
    public static byte[] serialize(Object obj) {
        Class clazz = (Class) obj.getClass();
        LinkedBuffer buffer = BUFFERS.get();
        if (buffer == null) {//存储buffer到线程局部变量中,避免每次序列化操作都分配内存提高序列化性能
            buffer = LinkedBuffer.allocate(512);
            BUFFERS.set(buffer);
        }
        try {
            Object serializeObject = obj;
            Schema schema = WRAPPER_SCHEMA;
            if (clazz.isArray() || Collection.class.isAssignableFrom(clazz)
                    || Map.class.isAssignableFrom(clazz) || Set.class.isAssignableFrom(clazz)) {//Protostuff 不支持序列化/反序列化数组、集合等对象,特殊处理
                serializeObject = SerializeDeserializeWrapper.builder(obj);
            } else {
                schema = RuntimeSchema.getSchema(clazz);
            }
            return ProtostuffIOUtil.toByteArray(serializeObject, schema, buffer);
        } finally {
            buffer.clear();
        }
    }

    /**
     * 反序列化对象
     *
     * @param data 需要反序列化的二进制数组
     * @param clazz 反序列化后的对象class
     * @param  反序列化后的对象类型
     * @return 反序列化后的实例对象
     */
    public static  T deserialize(Class clazz, byte[] data) {
        if (clazz.isArray() || Collection.class.isAssignableFrom(clazz)
                || Map.class.isAssignableFrom(clazz) || Set.class.isAssignableFrom(clazz)) {//Protostuff 不支持序列化/反序列化数组、集合等对象,特殊处理
            SerializeDeserializeWrapper wrapper = new SerializeDeserializeWrapper<>();
            ProtostuffIOUtil.mergeFrom(data, wrapper, WRAPPER_SCHEMA);
            return wrapper.getData();
        } else {
            Schema schema = RuntimeSchema.getSchema(clazz);
            T message = schema.newMessage();
            ProtostuffIOUtil.mergeFrom(data, message, schema);
            return message;
        }
    }

    /**
     * 

* 序列化/反序列化对象包装类 专为基于 Protostuff 进行序列化/反序列化而定义。 Protostuff * 是基于POJO进行序列化和反序列化操作。 如果需要进行序列化/反序列化的对象不知道其类型,不能进行序列化/反序列化; * 比如Map、List、String、Enum等是不能进行正确的序列化/反序列化。 * 因此需要映入一个包装类,把这些需要序列化/反序列化的对象放到这个包装类中。 这样每次 Protostuff * 都是对这个类进行序列化/反序列化,不会出现不能/不正常的操作出现 *

* * @author butioy */ static class SerializeDeserializeWrapper { private T data; public static SerializeDeserializeWrapper builder(T data) { SerializeDeserializeWrapper wrapper = new SerializeDeserializeWrapper<>(); wrapper.setData(data); return wrapper; } public T getData() { return data; } public void setData(T data) { this.data = data; } } public static void main(String[] args) throws Exception { System.out.println("String[abcd]:" + SerializationUtil.serialize("abcd").length); byte[] array = "abcd".getBytes(); Class c = String[].class; //System.out.println(new String(SerializationUtil.deserialize(byte[].class, SerializationUtil.serialize(array)))); System.out.println("array:" + SerializationUtil.serialize(array).length); System.out.println(SerializationUtil.deserialize(byte[].class, SerializationUtil.serialize(array)).getClass()); //System.out.println(SerializationUtil.deserialize(byte[].class, SerializationUtil.serialize(array)).getClass()); //LinkedList list = new LinkedList<>(); Set list = new HashSet<>(); list.add("aa"); list.add("bb"); System.out.println(SerializationUtil.serialize(list).length); //System.out.println(SerializationUtil.deserialize(LinkedList.class, SerializationUtil.serialize(list))); //System.out.println(SerializationUtil.deserialize(LinkedList.class, SerializationUtil.serialize(list)).getClass()); System.out.println(SerializationUtil.deserialize(HashSet.class, SerializationUtil.serialize(list))); System.out.println(SerializationUtil.deserialize(HashSet.class, SerializationUtil.serialize(list)).getClass()); } }

maven依赖:

       
            io.protostuff
            protostuff-core
            1.6.0
       

       
            io.protostuff
            protostuff-runtime
            1.6.0
       

你可能感兴趣的:(Java精品工具类)