在項(xiàng)目中使用Protobuf協(xié)議實(shí)現(xiàn)數(shù)據(jù)傳輸(二)

上篇已經(jīng)簡單的分析了什么是ProtoBuf協(xié)議的優(yōu)缺點(diǎn)、簡單的環(huán)境配置、項(xiàng)目中的簡單使用和一些編寫.Proto文件的注意點(diǎn),下面我們更加深入一下ProtoBuf的語法及高級使用(非常感謝Carson_Ho大神的博文指導(dǎo))

從Google官方例子進(jìn)行語法深入

Google官方例子:

syntax = "proto2";//聲明proto版本,2.0與3.0以后語法差異很大

package tutorial;//// 關(guān)注1:包名

option java_package = "com.example.tutorial";
option java_outer_classname = "AddressBookProtos";//// 關(guān)注2:option選項(xiàng)

message Person {//// 關(guān)注3:消息模型
  required string name = 1;
  required int32 id = 2;
  optional string email = 3;

  enum PhoneType {
MOBILE = 0;
HOME = 1;
WORK = 2;
  }

  message PhoneNumber {
required string number = 1;
optional PhoneType type = 2 [default = HOME];
  }

  repeated PhoneNumber phones = 4;
}

message AddressBook {
  repeated Person people = 1;
}

針對上述官方例子的注釋,下面一一分析

關(guān)注點(diǎn)1:包名

作用:防止不同 .proto 項(xiàng)目間命名 發(fā)生沖突

ProtoBuf包的解析過程如下

  • Protocol buffer 的類型名稱解析與 C++ 一致:從 最內(nèi)部 開始查找,依次 向外 進(jìn)行
    每個包會被看作是其父類包的內(nèi)部類
  • Protocol buffer 編譯器會解析 .proto文件中定義的所有類型名
    生成器會根據(jù) 不同語言 生成 對應(yīng)語言 的代碼文件
  • 即對 不同語言 使用了 不同的規(guī)則 進(jìn)行處理
  • Protoco Buffer提供 C++、Java、Python 三種語言的 API

關(guān)注點(diǎn)2:option選項(xiàng)

作用:影響 特定環(huán)境下 的處理方式,但不改變整個文件聲明的含義

常用Option選項(xiàng):(因?yàn)槭褂糜邢?,簡單列舉常見的)

option java_package = "com.crf.jason.myapplication";
// 定義:Java包名
// 作用:指定生成的類應(yīng)該放在什么Java包名下
// 注:如不顯式指定,默認(rèn)包名為:按照應(yīng)用名稱倒序方式進(jìn)行排序
option java_outer_classname="Demo";
// 定義:類名
// 作用:生成對應(yīng).java 文件的類名(不能跟下面message的類名相同)
// 注:如不顯式指定,則默認(rèn)為把.proto文件名轉(zhuǎn)換為首字母大寫來生成
// 如.proto文件名="book.proto",默認(rèn)情況下,將使用 "BookOuterClass" 做為類名

option optimize_for = ***;
// 作用:影響 C++  & java 代碼的生成
// ***參數(shù)如下:
// 1. SPEED (默認(rèn))::protocol buffer編譯器將通過在消息類型上執(zhí)行序列化、語法分析及其他通用的操作。(最優(yōu)方式)
// 2. CODE_SIZE::編譯器將會產(chǎn)生最少量的類,通過共享或基于反射的代碼來實(shí)現(xiàn)序列化、語法分析及各種其它操作。
  // 特點(diǎn):采用該方式產(chǎn)生的代碼將比SPEED要少很多, 但是效率較低;
  // 使用場景:常用在 包含大量.proto文件 但 不追求效率 的應(yīng)用中。
//3.  LITE_RUNTIME::編譯器依賴于運(yùn)行時 核心類庫 來生成代碼(即采用libprotobuf-lite 替代libprotobuf)。
  // 特點(diǎn):這種核心類庫要比全類庫小得多(忽略了 一些描述符及反射 );編譯器采用該模式產(chǎn)生的方法實(shí)現(xiàn)與SPEED模式不相上下,產(chǎn)生的類通過實(shí)現(xiàn) MessageLite接口,但它僅僅是Messager接口的一個子集。
  // 應(yīng)用場景:移動手機(jī)平臺應(yīng)用
  • Google官方還提供了在ProtoBuf中允許 自定義選項(xiàng)并且使用,具體請參考:傳送門

關(guān)注點(diǎn)3:消息模型

作用:真正用于描述 數(shù)據(jù)結(jié)構(gòu)

在.proto消息模型中主要有 消息對象&字段

Protobuf中的消息對象

  • 一個消息對象(Message) = 一個 結(jié)構(gòu)化數(shù)據(jù)
  • 消息對象用 修飾符 message 修飾
  • 消息對象 含有 字段:消息對象(Message)里的 字段 = 結(jié)構(gòu)化數(shù)據(jù) 里的成員變量

注意:

  • 在一個.proto文件可以定義多個消息對象

      message Person{//level 0
          string name=1;
          int32 age=2;
           string email=3;
      ...
      }
      message Car{
       string carName=1;
      int32 price=2;
      }
    
  • 在一個消息對象里面可以定義另外一個消息對象(嵌套)

      message Person{//level 0
          string name=1;
          int32 age=2;
           string email=3;
      enum Phonetype{
           MOBILE=0;
          HOME=1;
      }
      message PhoneNumber{//level 1
       string number=1;
      }
      }
    

Protobuf中消息對象的字段

字段

組成:字段 = 字段修飾符 + 字段類型 +字段名 +標(biāo)識號(主要針對proto2以前版本)

// required int32 id = 1;

字段 = 字段類型 +字段名 +標(biāo)識號(主要針對proto3及以后版本)

int32 id = 1;
字段類型

一個消息對象 可以將 其他消息對象類型 用作字段類型

  • 使用同一個 .proto 文件里的消息類型

  • 使用 內(nèi)部消息類型

     先在 消息類型 中定義 其他消息類型 ,然后再使用(嵌套)
    
         message Person{//level 0
             string name=1;
             int32 age=2;
             string email=3;
            enum Phonetype{
                MOBILE=0;
                HOME=1;
            }
             message PhoneNumber{//level 1
              string number=1;
              Person person=2;
             }
             PhoneNumber phoneNumber=4;//這里就是直接使用剛才定義的PhoneNumber消息類型
         }
         message Car{
             string carName=1;
             int32 price=2;
             Person.PhoneNumber phoneNumber=3;
         }
    
  • 使用 外部消息類型

     即外部重用,需要 用作字段類型的消息類型 定義在 該消息類型外部
    
         message Person{//level 0
             string name=1;
             int32 age=2;
             string email=3;
            enum Phonetype{
                MOBILE=0;
                HOME=1;
            }
             message PhoneNumber{//level 1
              string number=1;
              Person person=2;//這里就是使用外部消息類型 person
             }
             PhoneNumber phoneNumber=4;
         }
         message Car{
             string carName=1;
             int32 price=2;
             Person.PhoneNumber phoneNumber=3;
         }
    
  • 使用 外部消息的內(nèi)部消息類型

         message Person{//level 0
             string name=1;
             int32 age=2;
             string email=3;
            enum Phonetype{
                MOBILE=0;
                HOME=1;
            }
             message PhoneNumber{//level 1
              string number=1;
              Person person=2;
             }
             PhoneNumber phoneNumber=4;
         }
         message Car{
             string carName=1;
             int32 price=2;
             Person.PhoneNumber phoneNumber=3;//這里使用外部消息類型Person的PhoneNumber內(nèi)部消息類型
         }
    
  • 使用不同 .proto 文件里的消息類型

    作用:需要在 A.proto文件 使用 B.proto文件里的消息類型

    在 A.proto文件 通過導(dǎo)入( import) B.proto文件中來使用 B.proto文件 里的消息類型

  • 將 消息對象類型 用在 RPC(遠(yuǎn)程方法調(diào)用)系統(tǒng)

    具體實(shí)現(xiàn)請移步:大神博客

關(guān)于ProtoBuf在項(xiàng)目中的實(shí)踐的高級用法請關(guān)注:下一篇博客:在項(xiàng)目中使用Protobuf協(xié)議實(shí)現(xiàn)數(shù)據(jù)傳輸(三)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容