基於protostuff的序列化工具類開發

hahadelphi發表於2021-09-09

[toc]


基於protostuff的序列化工具類開發

前言

前面在介紹protostuff的基本使用時(可以參考文章protostuff基本使用),都是針對某個類寫的序列化和反序列化方法,顯然這樣不具有通用性,例如在進行遠端過程呼叫時,傳輸的物件並不唯一,這時就需要開發具有通用性的序列化工具類,即不管序列化的物件是什麼型別,都可以使用該工具類進行序列化。下面就來開發這樣的工具類。

基於這個需要,下面會開發兩個序列化工具類,一個是不具有快取功能的SerializationUtil,一個是具有快取功能的增強版本SerializationUtil2

需要注意的是,protostuff序列化工具類的開發需要大量使用到Java泛型的知識,因此在閱讀這些原始碼時應該需要具有一定的泛型知識儲備,否則程式碼閱讀起來會比較難懂,儘管我已經全部加了註釋。

protostuff序列化工具類SerializationUtil

下面直接給出原始碼:

package cn.xpleaf.protostuff.netty.utils;import com.dyuproject.protostuff.LinkedBuffer;import com.dyuproject.protostuff.ProtostuffIOUtil;import com.dyuproject.protostuff.runtime.RuntimeSchema;/** * 序列化工具類,基於Protostuff實現(其基於Google Protobuf實現) *  * @author yeyonghao * */public class SerializationUtil {    /**     * 序列化方法,將物件序列化為位元組陣列(物件 ---> 位元組陣列)     *      * @param obj     * @return     */    @SuppressWarnings("unchecked")    public static  byte[] serialize(T obj) {        // 獲取泛型物件的型別        Class clazz = (Class) obj.getClass();        // 建立泛型物件的schema物件        RuntimeSchema schema = RuntimeSchema.createFrom(clazz);        // 建立LinkedBuffer物件        LinkedBuffer buffer = LinkedBuffer.allocate(LinkedBuffer.DEFAULT_BUFFER_SIZE);        // 序列化        byte[] array = ProtostuffIOUtil.toByteArray(obj, schema, buffer);        // 返回序列化物件        return array;    }    /**     * 反序列化方法,將位元組陣列反序列化為物件(位元組陣列 ---> 物件)     *      * @param data     * @param clazz     * @return     */    public static  T deserialize(byte[] data, Class clazz) {        // 建立泛型物件的schema物件        RuntimeSchema schema = RuntimeSchema.createFrom(clazz);        // 根據schema例項化物件        T message = schema.newMessage();        // 將位元組陣列中的資料反序列化到message物件        ProtostuffIOUtil.mergeFrom(data, message, schema);        // 返回反序列化物件        return message;    }}

protostuff序列化工具類SerializationUtil2

SerializationUtil的問題在於,每次呼叫序列化方法和反序列化方法時都需要重新生成一個schema物件,所以可以把生成的schema物件儲存起來,在下一次呼叫方法時就不需要重新生成這些schema物件,這樣可以提高序列化和反序列化的效能。

package cn.xpleaf.protostuff.netty.utils;import java.util.Map;import java.util.concurrent.ConcurrentHashMap;import com.dyuproject.protostuff.LinkedBuffer;import com.dyuproject.protostuff.ProtostuffIOUtil;import com.dyuproject.protostuff.runtime.RuntimeSchema;/** * 具備快取功能的序列化工具類,基於Protostuff實現(其基於Google Protobuf實現) *  * @author yeyonghao * */public class SerializationUtil2 {    // 快取schema物件的map    private static Map, RuntimeSchema>> cachedSchema = new ConcurrentHashMap, RuntimeSchema>>();    /**     * 根據獲取相應型別的schema方法     *      * @param clazz     * @return     */    @SuppressWarnings({ "unchecked", "unused" })    private  RuntimeSchema getSchema(Class clazz) {        // 先嚐試從快取schema map中獲取相應型別的schema        RuntimeSchema schema = (RuntimeSchema) cachedSchema.get(clazz);        // 如果沒有獲取到對應的schema,則建立一個該型別的schema        // 同時將其新增到schema map中        if (schema == null) {            schema = RuntimeSchema.createFrom(clazz);            if (schema != null) {                cachedSchema.put(clazz, schema);            }        }        // 返回schema物件        return schema;    }    /**     * 序列化方法,將物件序列化為位元組陣列(物件 ---> 位元組陣列)     *      * @param obj     * @return     */    @SuppressWarnings("unchecked")    public static  byte[] serialize(T obj) {        // 獲取泛型物件的型別        Class clazz = (Class) obj.getClass();        // 建立泛型物件的schema物件        RuntimeSchema schema = RuntimeSchema.createFrom(clazz);        // 建立LinkedBuffer物件        LinkedBuffer buffer = LinkedBuffer.allocate(LinkedBuffer.DEFAULT_BUFFER_SIZE);        // 序列化        byte[] array = ProtostuffIOUtil.toByteArray(obj, schema, buffer);        // 返回序列化物件        return array;    }    /**     * 反序列化方法,將位元組陣列反序列化為物件(位元組陣列 ---> 物件)     *      * @param data     * @param clazz     * @return     */    public static  T deserialize(byte[] data, Class clazz) {        // 建立泛型物件的schema物件        RuntimeSchema schema = RuntimeSchema.createFrom(clazz);        // 根據schema例項化物件        T message = schema.newMessage();        // 將位元組陣列中的資料反序列化到message物件        ProtostuffIOUtil.mergeFrom(data, message, schema);        // 返回反序列化物件        return message;    }}

測試

測試程式碼如下:

package cn.xpleaf.protostuff.netty.utils;import static org.junit.Assert.*;import org.junit.Test;import cn.xpleaf.pojo.User;public class TestUtil {    @Test    public void testUtil01() throws Exception {        User user = new User("xpleaf", 10);        System.out.println(user);        // 序列化        byte[] array = SerializationUtil.serialize(user);        // 反序列化        User user2 = SerializationUtil.deserialize(array, User.class);        System.out.println(user2);        // 判斷值是否相等        System.out.println(user.toString().equals(user2.toString()));    }    @Test    public void testUtil02() throws Exception {        User user = new User("xpleaf", 10);        System.out.println(user);        // 序列化        byte[] array = SerializationUtil2.serialize(user);        // 反序列化        User user2 = SerializationUtil2.deserialize(array, User.class);        System.out.println(user2);        // 判斷值是否相等        System.out.println(user.toString().equals(user2.toString()));    }}

執行testUtil01時的輸出結果如下:

User [name=xpleaf, age=10]User [name=xpleaf, age=10]true

執行testUtil02時的輸出結果如下:

User [name=xpleaf, age=10]User [name=xpleaf, age=10]true

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/2471/viewspace-2813881/,如需轉載,請註明出處,否則將追究法律責任。

相關文章