protostuff序列化使用

背景

最近在作項目的時候須要使用持久化功能,1.0版本中使用的akka自帶的持久化功能,使用的是akka persist支持的redis插件,在使用的過程當中踩了一些坑。所以,在而2.0版本中考慮本身往redis中持久化。要作持久化,必須考慮對象的序列化問題。序列化的方法不少,可使用java自帶的序列化機制,可是時間效率不太好。所以在kryo和protobuffer之間徘徊。由於之前使用過grpc,須要手動編寫proto文件,而後利用插件生成代碼,以爲很麻煩。可是經過搜索瞭解到還有一個protostuff不須要編寫proto文件這個麻煩的步驟,而且效率還很好。所以,學習了下。java

引入依賴

<dependency>
      <groupId>io.protostuff</groupId>
      <artifactId>protostuff-core</artifactId>
      <version>1.6.0</version>
 </dependency>
<dependency>
     <groupId>io.protostuff</groupId>
     <artifactId>protostuff-runtime</artifactId>
     <version>1.6.0</version>
 </dependency>

javaBean

編寫須要序列化和反序列化的對象git

public class User {

    private String name;

    private int age;

    public User(String name, int age) {
        this.name = name;
        this.age = age;
    }
}

public class Group {

    private String id;

    private String name;

    private List<User> users;

    public Group(String id, String name, List<User> users) {
        this.id = id;
        this.name = name;
        this.users = users;
    }
}

開發序列化和反序列化工具類

public class ProtostuffUtils {
    /**
     * 避免每次序列化都從新申請Buffer空間
     */
    private static LinkedBuffer buffer = LinkedBuffer.allocate(LinkedBuffer.DEFAULT_BUFFER_SIZE);
    /**
     * 緩存Schema
     */
    private static Map<Class<?>, Schema<?>> schemaCache = new ConcurrentHashMap<Class<?>, Schema<?>>();

    /**
     * 序列化方法,把指定對象序列化成字節數組
     *
     * @param obj
     * @param <T>
     * @return
     */
    @SuppressWarnings("unchecked")
    public static <T> byte[] serialize(T obj) {
        Class<T> clazz = (Class<T>) obj.getClass();
        Schema<T> schema = getSchema(clazz);
        byte[] data;
        try {
            data = ProtostuffIOUtil.toByteArray(obj, schema, buffer);
        } finally {
            buffer.clear();
        }

        return data;
    }

    /**
     * 反序列化方法,將字節數組反序列化成指定Class類型
     *
     * @param data
     * @param clazz
     * @param <T>
     * @return
     */
    public static <T> T deserialize(byte[] data, Class<T> clazz) {
        Schema<T> schema = getSchema(clazz);
        T obj = schema.newMessage();
        ProtostuffIOUtil.mergeFrom(data, obj, schema);
        return obj;
    }

    @SuppressWarnings("unchecked")
    private static <T> Schema<T> getSchema(Class<T> clazz) {
        Schema<T> schema = (Schema<T>) schemaCache.get(clazz);
        if (schema == null) {
            //這個schema經過RuntimeSchema進行懶建立並緩存
            //因此能夠一直調用RuntimeSchema.getSchema(),這個方法是線程安全的
            schema = RuntimeSchema.getSchema(clazz);
            if (schema == null) {
                schemaCache.put(clazz, schema);
            }
        }

        return schema;
    }

    public static void main(String[] args){
        final User user1 = new User("aaa",20);
        final User user2 = new User("bbb",21);
        List<User> users = new ArrayList<User>(){{add(user1);add(user2);}};
        Group group = new Group("id_1","group1",users);

        byte[] bytes = ProtostuffUtils.serialize(group);
        System.out.println("序列化後: " + bytes.length);

        Group group1 = ProtostuffUtils.deserialize(bytes,Group.class);
        System.out.println("反序列化後: " + group1.getName());

    }

運行結果以下:github

序列化後: 32
反序列化後: group1

工具類參考博客:https://blog.csdn.net/oppo5630/article/details/80173520
protostuff的github地址:https://github.com/protostuff/protostuffredis

相關文章
相關標籤/搜索