最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

基于Protobuf動(dòng)態(tài)解析在Java中的應(yīng)用 包含例子程序

 更新時(shí)間:2017年07月24日 08:32:41   投稿:jingxian  
下面小編就為大家?guī)?lái)一篇基于Protobuf動(dòng)態(tài)解析在Java中的應(yīng)用 包含例子程序。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧

最近在做ProtoBuf相關(guān)的項(xiàng)目,其中用到了動(dòng)態(tài)解析,網(wǎng)上看了下相關(guān)資料和博文都比較少,自己來(lái)寫(xiě)一個(gè)記錄一下學(xué)習(xí)過(guò)程。

Protocol Buffers是結(jié)構(gòu)化數(shù)據(jù)格式標(biāo)準(zhǔn),提供序列化和反序列方法,用于存儲(chǔ)和交換。語(yǔ)言中立,平臺(tái)無(wú)關(guān)、可擴(kuò)展。目前官方提供了C++、Java、Python API,也有其他語(yǔ)言的開(kāi)源api(比如php)??赏ㄟ^(guò) .proto文件生成對(duì)應(yīng)語(yǔ)言的類(lèi)代碼
如果已知protobuf內(nèi)容對(duì)應(yīng)的是哪個(gè)類(lèi)對(duì)象,則可以直接使用反序列化方法搞定(Xxx.parseFrom(inputStream)由二進(jìn)制轉(zhuǎn)換,TextFormat.merge(string, xxxBuilder)由文本轉(zhuǎn)換)

而我們經(jīng)常遇到的情況是,拿到一個(gè)被protobuf序列化的二進(jìn)制內(nèi)容,但不知道它的類(lèi)型,無(wú)法獲得對(duì)應(yīng)的類(lèi)對(duì)象。這種多見(jiàn)于需要處理各種各樣未知的ProtoBuf對(duì)象的系統(tǒng)。ProtoBuf提供了動(dòng)態(tài)解析機(jī)制來(lái)解決這個(gè)問(wèn)題,它要求提供二進(jìn)制內(nèi)容的基礎(chǔ)上,再提供對(duì)應(yīng)類(lèi)的Descriptor對(duì)象,在解析時(shí)通過(guò)DynamicMessage類(lèi)的成員方法來(lái)獲得對(duì)象結(jié)果。
最后問(wèn)題就是Descriptor對(duì)象從哪里來(lái)?這是通過(guò)protoc --descriptor_set_out=$outputpath 命令生成descriptor文件,進(jìn)而得到的。

代碼如下:

 cinema.proto

option java_package="com.liulei.cinema";

enum MovieType{
 CHILDREN=1;
 ADULT=2;
 NORMAL=3;
 OHTER=4;
}

enum Gender{
 MAN=1;
 WOMAN=2;
 OTHER=3;
}

message Movie{
 required string name=1;
 required MovieType type=2;
 optional int32 releaseTimeStamp=3;
 optional string description=4;
}

message Customer{
 required string name=1;
 optional Gender gender=2;
 optional int32 birthdayTimeStamp=3;
}

message Ticket{
 required int32 id=1;
 required Movie movie=2;
 required Customer customer=3;
}

Main.java

public static void main( String[] args ) {

  Cinema.Movie.Builder movieBuilder = Cinema.Movie.newBuilder();
  movieBuilder.setName("The Shining");
  movieBuilder.setType(Cinema.MovieType.ADULT);
  movieBuilder.setReleaseTimeStamp(327859200);

  System.out.println("Dynamic Message Parse by proto file");
  try {
   byte[] buffer3 = new byte[movieBuilder.build().getSerializedSize()];
   CodedOutputStream codedOutputStream3 = CodedOutputStream.newInstance(buffer3);
   try {
    movieBuilder.build().writeTo(codedOutputStream3);
    System.out.println(buffer3);
   } catch (IOException e) {
    e.printStackTrace();
   }
   String protocCMD = "protoc --descriptor_set_out=cinema.description ./cinema.proto --proto_path=.";
   Process process = Runtime.getRuntime().exec(protocCMD);
   process.waitFor();
   int exitValue = process.exitValue();
   if (exitValue != 0) {
    System.out.println("protoc execute failed");
    return;
   }
   Descriptors.Descriptor pbDescritpor = null;
   DescriptorProtos.FileDescriptorSet descriptorSet = DescriptorProtos.FileDescriptorSet.parseFrom(new FileInputStream("./cinema.description"));
   for (DescriptorProtos.FileDescriptorProto fdp : descriptorSet.getFileList()) {
    Descriptors.FileDescriptor fileDescriptor = Descriptors.FileDescriptor.buildFrom(fdp, new Descriptors.FileDescriptor[]{});
    for (Descriptors.Descriptor descriptor : fileDescriptor.getMessageTypes()) {
     if (descriptor.getName().equals("Movie")) {
      System.out.println("Movie descriptor found");
      pbDescritpor = descriptor;
      break;
     }
    }
   }
   if (pbDescritpor == null) {
    System.out.println("No matched descriptor");
    return;
   }
   DynamicMessage.Builder pbBuilder = DynamicMessage.newBuilder(pbDescritpor);

   Message pbMessage = pbBuilder.mergeFrom(buffer3).build();
   System.out.println(pbMessage);

  } catch (Exception e) {
   System.out.println("Exception");
   e.printStackTrace();
  }
 }

執(zhí)行結(jié)果:

Dynamic Message Parse From byte array
[B@597ccf6e
Movie descriptor found
name: "The Shining"
type: ADULT
releaseTimeStamp: 327859200

 解釋具體過(guò)程:

0.首先對(duì).proto文件使用protoc命令,生成的descriptor文件中包含多個(gè)類(lèi)對(duì)應(yīng)的descriptor類(lèi)信息(序列化的DescriptorSet內(nèi)容)

1.首先取出序列化的DescriptorSet內(nèi)容,F(xiàn)ileDescriptorSet.parseFrom方法反序列化得到FileDescriptorSet對(duì)象

2.取出對(duì)應(yīng)message類(lèi)型的Descriptor。

 DescriptorSet成員方法getFileList(),拿到多個(gè)FileDescriptorProto對(duì)象,再構(gòu)建對(duì)應(yīng)FileDescriptor。
 FileDescriptor的成員方法getMessageTypes()得到所有Message的Descriptor對(duì)象,找到對(duì)應(yīng)名字的Descriptor

3.用Descriptor對(duì)象反序列化對(duì)象

構(gòu)建DynamicMessage.Builder對(duì)象builder,再調(diào)用builder的mergeFrom/merge方法得到Message對(duì)象

其中Descriptor相關(guān)類(lèi):

DescriptorProtos.DescriptorSet:protoc編譯出來(lái)類(lèi)文件中包含這個(gè)類(lèi),描述多個(gè).proto文件中的類(lèi)

DescriptorProtos.FileDescriptorProto:描述一個(gè)完整的.proto文件中的類(lèi)

DescriptorProtos.FileDescriptor:由DescriptorProtos.FileDescriptorProto構(gòu)建而來(lái)(buildFrom),描述1個(gè)完整.proto文件中的所有內(nèi)容,包括message類(lèi)型的Descriptor和其他被導(dǎo)入文件的Descriptor。

getMessageTypes()方法:返回List<Descriptors.Descriptor>。得到FileDescriptor內(nèi),所有message類(lèi)型直接兒子的Descriptor列表   

DescriptorProtos.Descriptor:描述一個(gè)message類(lèi)型,通過(guò)getName()得到message的類(lèi)名

以上這篇基于Protobuf動(dòng)態(tài)解析在Java中的應(yīng)用 包含例子程序就是小編分享給大家的全部?jī)?nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • SpringBoot整合tkMapper的方法

    SpringBoot整合tkMapper的方法

    項(xiàng)目使用SpringBoot2.0,H2數(shù)據(jù)庫(kù),使用了?Lombok?簡(jiǎn)化代碼,下面是本人使用SpringBoot整合tkMapper的一個(gè)小demo,記錄下來(lái)本人在此處踩得坑
    2022-11-11
  • Java中?springcloud.openfeign應(yīng)用案例解析

    Java中?springcloud.openfeign應(yīng)用案例解析

    使用OpenFeign能讓編寫(xiě)Web?Service客戶(hù)端更加簡(jiǎn)單,使用時(shí)只需定義服務(wù)接口,然后在上面添加注解,OpenFeign也支持可拔插式的編碼和解碼器,這篇文章主要介紹了Java中?springcloud.openfeign應(yīng)用案例解析,需要的朋友可以參考下
    2024-06-06
  • springsecurity 企業(yè)微信登入的實(shí)現(xiàn)示例

    springsecurity 企業(yè)微信登入的實(shí)現(xiàn)示例

    本文主要介紹了springsecurity 企業(yè)微信登入的實(shí)現(xiàn)示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2022-04-04
  • Java的抽象方法和抽象類(lèi)實(shí)例詳解

    Java的抽象方法和抽象類(lèi)實(shí)例詳解

    這篇文章主要介紹了Java的抽象方法和抽象類(lèi),結(jié)合實(shí)例形式詳細(xì)分析了java抽象方法和抽象類(lèi)的相關(guān)原理、使用方法及操作注意事項(xiàng),需要的朋友可以參考下
    2019-09-09
  • java遞歸處理單位人員組織機(jī)構(gòu)樹(shù)方式

    java遞歸處理單位人員組織機(jī)構(gòu)樹(shù)方式

    這篇文章主要介紹了java遞歸處理單位人員組織機(jī)構(gòu)樹(shù)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-08-08
  • JAVA中的靜態(tài)代理、動(dòng)態(tài)代理以及CGLIB動(dòng)態(tài)代理總結(jié)

    JAVA中的靜態(tài)代理、動(dòng)態(tài)代理以及CGLIB動(dòng)態(tài)代理總結(jié)

    本篇文章主要介紹了JAVA中的靜態(tài)代理、動(dòng)態(tài)代理以及CGLIB動(dòng)態(tài)代理總結(jié),具有一定的參考價(jià)值,有興趣的可以了解一下
    2017-08-08
  • 詳解MyBatis模糊查詢(xún)LIKE的三種方式

    詳解MyBatis模糊查詢(xún)LIKE的三種方式

    模糊查詢(xún)也是數(shù)據(jù)庫(kù)SQL中使用頻率很高的SQL語(yǔ)句,這篇文章主要介紹了詳解MyBatis模糊查詢(xún)LIKE的三種方式,非常具有實(shí)用價(jià)值,需要的朋友可以參考下
    2018-10-10
  • Spring Cloud GateWay 路由轉(zhuǎn)發(fā)規(guī)則介紹詳解

    Spring Cloud GateWay 路由轉(zhuǎn)發(fā)規(guī)則介紹詳解

    這篇文章主要介紹了Spring Cloud GateWay 路由轉(zhuǎn)發(fā)規(guī)則介紹詳解,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2019-05-05
  • 作為Java程序員應(yīng)該掌握的10項(xiàng)技能

    作為Java程序員應(yīng)該掌握的10項(xiàng)技能

    這篇文章主要介紹了作為Java程序員應(yīng)該掌握的10項(xiàng)技能,包括java的知識(shí)點(diǎn)與相關(guān)的技能,對(duì)于java的學(xué)習(xí)有不錯(cuò)的參考借鑒價(jià)值,需要的朋友可以參考下
    2015-05-05
  • Java判斷ip是否為IPV4或IPV6地址的多種方式

    Java判斷ip是否為IPV4或IPV6地址的多種方式

    本文主要介紹了Java判斷ip是否為IPV4或IPV6地址的多種方式,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-03-03

最新評(píng)論

巫溪县| 鄂伦春自治旗| 铁岭市| 荣昌县| 神农架林区| 韩城市| 封丘县| 高台县| 仁化县| 沙湾县| 乐业县| 桑日县| 二连浩特市| 甘孜县| 额尔古纳市| 高清| 庆阳市| 渑池县| 遵义市| 南华县| 云林县| 抚宁县| 曲阳县| 伊金霍洛旗| 芜湖市| 桂阳县| 泌阳县| 凤城市| 汪清县| 和顺县| 塘沽区| 吉木乃县| 顺义区| 都安| 永平县| 资源县| 当阳市| 旬阳县| 嘉义县| 天长市| 广汉市|