小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

《從零開(kāi)始搭建游戲服務(wù)器》 序列化工具(最優(yōu)版Protostuff)

 WindySky 2017-08-13

前言:

之前使用protobuf工具來(lái)解析表格數(shù)據(jù)和定制網(wǎng)絡(luò)協(xié)議,但是為了網(wǎng)絡(luò)安全和壓縮數(shù)據(jù)大小,有時(shí)候需要對(duì)數(shù)據(jù)進(jìn)行序列化,這就需要設(shè)計(jì)一個(gè)序列化工具類(lèi)來(lái)完成序列化和反序列化的操作。

框架的對(duì)比:

Java中幾個(gè)常用的序列化框架對(duì)比,包括:kryo、Hessian、Protostuff、Protostuff-Runtimejava.io

框架 優(yōu)點(diǎn) 缺點(diǎn)
kryo 速度快,序列化后體積小 跨語(yǔ)言支持比較復(fù)雜
Hessian 默認(rèn)支持跨語(yǔ)言 速度比較慢
java.io JDK自帶功能,使用方便,可序列化所有類(lèi) 速度慢,占空間大
Protostuff 速度快,基于protobuf 需要靜態(tài)編譯
Protostuff-Runtime 無(wú)需靜態(tài)編譯,但序列化之前需要預(yù)先傳入Schema 不支持無(wú)默認(rèn)構(gòu)造函數(shù)的類(lèi),反序列化時(shí)需要用戶(hù)自己初始化序列化后的對(duì)象,而此工具只負(fù)責(zé)對(duì)初始化后的對(duì)象進(jìn)行賦值

1.詳細(xì)分析:

  • protobuf 的一個(gè)缺點(diǎn)是需要數(shù)據(jù)結(jié)構(gòu)的預(yù)編譯過(guò)程,首先要編寫(xiě) .proto 格式的配置文件,再通過(guò) protobuf 提供的工具生成各種語(yǔ)言響應(yīng)的代碼。由于java具有反射和動(dòng)態(tài)代碼生成的能力,這個(gè)預(yù)編譯過(guò)程不是必須的,可以在代碼執(zhí)行時(shí)來(lái)實(shí)現(xiàn)。有個(gè) protostuff插件 已經(jīng)實(shí)現(xiàn)了這個(gè)功能。

  • protostuff 基于Google protobuf,但是提供了更多的功能和更簡(jiǎn)易的用法。其中,protostuff-runtime 實(shí)現(xiàn)了無(wú)需預(yù)編譯對(duì)Java bean進(jìn)行protobuf序列化/反序列化的能力。protostuff-runtime的局限是序列化前需預(yù)先傳入schema,反序列化不負(fù)責(zé)對(duì)象的創(chuàng)建只負(fù)責(zé)復(fù)制,因而必須提供默認(rèn)構(gòu)造函數(shù)。此外,protostuff 還可以按照protobuf的配置序列化成json/yaml/xml等格式。

2.坑點(diǎn)解決:

沒(méi)經(jīng)過(guò)修改過(guò)的 protostuff,性能方法還是有些缺陷,這里我在一篇關(guān)于 輕量級(jí)分布式 RPC 框架 博客中找到了據(jù)說(shuō)是當(dāng)前性能最優(yōu)的 優(yōu)化版Protostuff 的使用案例。
在原生的 Protostuff 中通過(guò)反射實(shí)例化java類(lèi)的時(shí)候,是通過(guò)使用 Class.newInstance() 方法來(lái)實(shí)現(xiàn)的,而前提就是這個(gè)類(lèi)java類(lèi)必須提供默認(rèn)構(gòu)造函數(shù)。
假如希望在java類(lèi)不提供默認(rèn)構(gòu)造函數(shù)的時(shí)候也能實(shí)現(xiàn)反射實(shí)例化,可以選擇使用 objenesis 來(lái)實(shí)例化java類(lèi),使用方式可以參考 objenesis官網(wǎng)。

3.框架選擇:

綜合上述的分析,最終我還是選擇了 Protostuff 框架來(lái)完成Protobuf數(shù)據(jù)的序列化,關(guān)于不支持無(wú)默認(rèn)構(gòu)造函數(shù)類(lèi)序列化的缺陷接下來(lái)通過(guò)使用 objenesis 也會(huì)得到解決。

自定義序列化工具類(lèi)

這里我們創(chuàng)建此工具類(lèi),取名為 SerializationUtil,使用Protostuff來(lái)序列化和反序列化Protobuf數(shù)據(jù):

1.庫(kù)引入:

首先要在pom.xml里添加com.dyuproject.protostuffobjenesis的jar包:

 <dependency>  
     <groupId>com.dyuproject.protostuff</groupId>  
     <artifactId>protostuff-core</artifactId>  
     <version>1.0.8</version>  
 </dependency>  

 <dependency>  
     <groupId>com.dyuproject.protostuff</groupId>  
     <artifactId>protostuff-runtime</artifactId>  
     <version>1.0.8</version>  
 </dependency>  
 <!-- Objenesis -->
 <dependency>
     <groupId>org.objenesis</groupId>
     <artifactId>objenesis</artifactId>
     <version>2.1</version>
 </dependency>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

2.工具類(lèi)編寫(xiě):

主要包含兩個(gè)核心的函數(shù):序列化函數(shù) Serializer 和反序列化函數(shù) Deserializer

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

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;

public class SerializationUtil {

    private static Map<Class<?>, Schema<?>> cachedSchema = new ConcurrentHashMap<>();

    private static Objenesis objenesis = new ObjenesisStd(true);

    private SerializationUtil() {
    }

    @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 {
            T message = (T) objenesis.newInstance(cls);
            Schema<T> schema = getSchema(cls);
            ProtostuffIOUtil.mergeFrom(data, message, schema);
            return message;
        } catch (Exception e) {
            throw new IllegalStateException(e.getMessage(), e);
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57

上面是引入 objenesis 之后的版本,優(yōu)點(diǎn)就是支持沒(méi)有提供默認(rèn)構(gòu)造函數(shù)的java類(lèi)的實(shí)例化,可以看到這里通過(guò) Class<T> cls = (Class<T>) obj.getClass(); 來(lái)實(shí)例化java類(lèi)的。ConcurrentHashMap是適用于高并發(fā)的Map數(shù)據(jù)結(jié)構(gòu)。

3.工具類(lèi)調(diào)用:

隨便定義一個(gè)Protobuf的協(xié)議類(lèi),假設(shè)為User,下面就是具體的序列化工具使用操作:

  • 序列化:

    byte[] data = SerializationUtil.serialize(user,User.class);  
    • 1
    • 1
  • 反序列化:

    User user2 = SerializationUtil.deserialize(data,User.class); 
    • 1
    • 1

參考資料:

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶(hù)發(fā)布,不代表本站觀(guān)點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買(mǎi)等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶(hù) 評(píng)論公約

    類(lèi)似文章 更多