All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.fartherp.framework.common.util.ProtobufSerializeUtil Maven / Gradle / Ivy

There is a newer version: 3.0.6
Show newest version
/*
 * Copyright (c) 2018. CK. All rights reserved.
 */

package com.github.fartherp.framework.common.util;

import com.dyuproject.protostuff.LinkedBuffer;
import com.dyuproject.protostuff.ProtobufIOUtil;
import com.dyuproject.protostuff.Schema;
import com.dyuproject.protostuff.runtime.RuntimeEnv;
import com.dyuproject.protostuff.runtime.RuntimeSchema;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.objenesis.Objenesis;
import org.objenesis.ObjenesisStd;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 序列化工具类(基于 Protostuff 实现)
 */
public class ProtobufSerializeUtil {

    private final static Map> cachedSchema = new ConcurrentHashMap>();

    private final static Objenesis objenesis = new ObjenesisStd(true);

    /**
     * logger
     */
    private static final Log logger = LogFactory.getLog(ProtobufSerializeUtil.class);

    /**
     * 序列化(对象 -> 字节数组),序列化所有属性字段.
     */
    public static  byte[] serialize(T obj) {
        return serialization(obj, null, null);
    }

    /**
     * 序列化(对象 -> 字节数组),只序列化对应的属性字段.
     */
    public static  byte[] serialize(T obj, String[] inclusives) {
        return serialization(obj, null, inclusives);
    }

    /**
     * 序列化(对象 -> 字节数组),排除对应的属性字段.
     */
    public static  byte[] serializeWithExclusions(T obj, String[] exclusions) {
        return serialization(obj, exclusions, null);
    }

    /**
     * 反序列化(字节数组 -> 对象),包含所有需要反序列化的属性字段.
     */
    public static  T deserialize(byte[] data, Class cls) {
        return deserialization(data, cls, null, null);
    }

    /**
     * 反序列化(字节数组 -> 对象),包含指定的需要反序列化的属性字段.
     */
    public static  T deserialize(byte[] data, Class cls, String[] fields) {
        return deserialization(data, cls, null, fields);
    }

    /**
     * 反序列化(字节数组 -> 对象),排除对应的属性字段.
     */
    public static  T deserializeWithExclusions(byte[] data, Class cls, String[] fields) {
        return deserialization(data, cls, fields, null);
    }

    private static  byte[] serialization(T obj, String[] exclusions, String[] inclusives) {
        if (null == obj) return null;
        @SuppressWarnings("unchecked")
        Class cls = (Class) obj.getClass();
        LinkedBuffer buffer = LinkedBuffer.allocate(LinkedBuffer.DEFAULT_BUFFER_SIZE);
        try {
            Schema schema = initSchema(exclusions, inclusives, cls);
            return ProtobufIOUtil.toByteArray(obj, schema, buffer);
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(e.getMessage(), e);
        } finally {
            buffer.clear();
        }
        return null;
    }

    private static  Schema initSchema(String[] exclusions, String[] inclusives, Class cls) {
        if (null != exclusions && exclusions.length != 0) {
            return getSchemaWithExclusion(cls, exclusions);
        } else if (null != inclusives && inclusives.length != 0) {
            return getSchemaWithInclusive(cls, inclusives);
        } else {
            return getSchema(cls);
        }
    }

    /**
     * 反序列化(字节数组 -> 对象),包含指定的需要反序列化的属性字段.
     */
    private static  T deserialization(byte[] data, Class cls, String[] exclusions, String[] inclusives) {
        if (data == null || data.length == 0)
            return null;
        try {
            T message = objenesis.newInstance(cls);
            Schema schema = initSchema(exclusions, inclusives, cls);
            ProtobufIOUtil.mergeFrom(data, message, schema);
            return message;
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(e.getMessage(), e);
        }
        return null;
    }

    private static String getKey(@SuppressWarnings("rawtypes") Class cls) {
        List sorts = getSortedFields(cls);
        return cls.getName() + sorts.toString();
    }

    private static String getKeyWithExclusion(@SuppressWarnings("rawtypes") Class cls, String[] fields) {
        List sorts = getSortedFields(cls);
        List exclusions = Arrays.asList(fields);
        sorts.removeAll(exclusions);
        return cls.getName() + sorts.toString();
    }

    private static String getKeyWithInclusion(@SuppressWarnings("rawtypes") Class cls, String[] fields) {
        List l = Arrays.asList(fields);
        //以下排序逻辑的初忠是为了对相同字段列表做去重操作的,而实际运行中,字段列表相同而序列顺序会有不同的情况,所以需要注释排序。
        /*List sorts = new ArrayList(l);
        Collections.sort(sorts);*/
        return cls.getName() + l.toString();
    }

    private static List getSortedFields(@SuppressWarnings("rawtypes") Class cls) {
        Field[] fields = cls.getDeclaredFields();
        String[] strs = new String[fields.length];

        int i = 0;
        for (Field field : fields) {
            strs[i] = field.getName();
            i++;
        }
        Arrays.sort(strs);
        return new ArrayList(Arrays.asList(strs));
    }

    private static  Schema getSchema(Class cls) {
        String key = getKey(cls);
        @SuppressWarnings("unchecked")
        Schema schema = (Schema) cachedSchema.get(key);
        if (schema == null) {
            schema = RuntimeSchema.createFrom(cls);
            cachedSchema.put(key, schema);
        }
        return schema;
    }

    private static  Schema getSchemaWithExclusion(Class cls, String[] fields) {
        String key = getKeyWithExclusion(cls, fields);

        @SuppressWarnings("unchecked")
        Schema schema = (Schema) cachedSchema.get(key);
        if (schema == null) {
            schema = RuntimeSchema.createFrom(cls, fields, RuntimeEnv.ID_STRATEGY);
            cachedSchema.put(key, schema);
        }
        return schema;
    }

    private static  Schema getSchemaWithInclusive(Class cls, String[] fields) {
        String key = getKeyWithInclusion(cls, fields);

        @SuppressWarnings("unchecked")
        Schema schema = (Schema) cachedSchema.get(key);
        if (schema == null) {
            Map map = new LinkedHashMap();
            for (String field : fields) {
                map.put(field, field);
            }
            schema = RuntimeSchema.createFrom(cls, map, RuntimeEnv.ID_STRATEGY);
            cachedSchema.put(key, schema);
        }
        return schema;
    }
}





© 2015 - 2025 Weber Informatics LLC | Privacy Policy