日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

proto的介绍和基础使用

發布時間:2024/9/30 编程问答 43 豆豆
生活随笔 收集整理的這篇文章主要介紹了 proto的介绍和基础使用 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

內容摘抄自書籍《Netty redis zookeeper高并發實戰》

Protobuf使用

proto文件來預先定義的消息格式。數據包是按照proto文件所定義的消息格式完成二進制碼流的編碼和解碼。proto文件,簡單地說,就是一個消息的協議文件,這個協議文件的后綴文件名為“.proto”。 作為演示,下面介紹一個非常簡單的proto文件:僅僅定義一個消息結構體,并且該消息結構體也非常簡單,僅包含兩個字段。實例如下:

// [開始頭部聲明] syntax = "proto3"; packagecom.crazymakercircle.netty.protocol; // [結束頭部聲明] // [開始 java選項配置] option java_package = "com.crazymakercircle.netty.protocol"; option java_outer_classname = "MsgProtos"; // [結束 java選項配置] // [開始消息定義] message Msg { uint32 id = 1; //消息IDstring content = 2;//消息內容 } // [結束消息定義]

例子:

syntax = "proto3"; message Model {int64 id = 1;string action = 2;string content = 3;string sender = 4;string receiver = 5;string extra = 6;string title = 7;string format = 8;int64 timestamp = 9; }

注:在idea中下載protobuf插件即可以高亮proto文件

在“.proto”文件的頭部聲明中,需要聲明“.proto”所使用的Protobuf協議版本,這里使用的是"proto3"。也可以使用舊一點的版本"proto2",兩個版本的消息格式有一些細微的不同。
默認的協議版本為"proto2"。

Protobuf支持很多語言,所以它為不同的語言提供了一些可選的聲明選項,選項的前面有option關鍵字。

“java_package”選項的作用為:在生成“proto”文件中消息的POJO類和Builder(構造者)的Java代碼時,將Java代碼放入指定的package中。

“java_outer_classname”選項的作用為:在生成“proto”文件所對應Java代碼時,所生產的Java外部類的名稱。 在“proto”文件中,使用message這個關鍵字來定義消息的結構體。在生成“proto”對應的Java代碼時,
每個具體的消息結構體都對應于一個最終的Java POJO類。消息結構體的字段對應到POJO類的屬性。也就是說,每定義一個“message”結構體相當于聲明一個Java中的類。并且message中可以內嵌message,就像java的內部類一樣。 每一個消息結構體可以有多個字段。定義一個字段的格式,簡單來說就是“類型名稱=編號”。
例如“string content=2;”,表示該字段是string類型,名為content,序號為2。字段序號表示為:在Protobuf數據包的序列化、反序列化時,該字段的具體排序。 在每一個“.proto”文件中,可以聲明多個“message”。大部分情況下,會把有依賴關系或者包含關系的message消息結構體寫入一個.proto文件。將那些沒有關聯關系的message消息結構體,分別寫入不同的文件,這樣便于管理。

Maven插件生成POJO和Builder

使用命令行生成Java類的操作比較煩瑣。另一種更加方便的方式是:使用protobuf-maven-plugin插件,它可非常方便地生成消息的POJO類和Builder(構造者)類的Java代碼。在Maven的pom文件中增加此plugin插件的配置項,具體如下:

<plugin><groupId>org.xolstice.maven.plugins</groupId><artifactId>protobuf-maven-plugin</artifactId><version>0.5.0</version><extensions>true</extensions><configuration><!--proto文件路徑--><protoSourceRoot>${project.basedir}/protobuf</protoSourceRoot><!--目標路徑--><outputDirectory>${project.build.sourceDirectory}</outputDirectory><!--設置是否在生成Java文件之前清空outputDirectory的文件--><clearOutputDirectory>false</clearOutputDirectory><!--臨時目錄--><temporaryProtoFileDirectory>${project.build.directory}/protoc-temp</temporaryProtoFileDirectory><!--protoc可執行文件路徑--><protocExecutable>${project.basedir}/protobuf/protoc3.6.1.exe</protocExecutable></configuration><executions><execution><goals><goal>compile</goal><goal>test-compile</goal></goals></execution></executions> </plugin>

protobuf-maven-plugin插件的配置項,具體介紹如下:
·protoSourceRoot:“proto”消息結構體文件的路徑。
·outputDirectory:生成的POJO類和Builder類的目標路徑。
·protocExecutable:Java代碼生成工具的protoc3.6.1.exe可執行文件的路徑。
配置好之后,執行插件的compile命令,Java代碼就利索生成了。或者在Maven的項目編譯時,POJO類和Builder類也會自動生成。

1.使用Builder構造者,構造POJO消息對象

package com.crazymakercircle.netty.protocol; //... public class ProtobufDemo {public static MsgProtos.MsgbuildMsg() {MsgProtos.Msg.BuilderpersonBuilder = MsgProtos.Msg.newBuilder();personBuilder.setId(1000);personBuilder.setContent("瘋狂創客圈:高性能學習社群");MsgProtos.Msg message = personBuilder.build(); return message;}//….. }

Protobuf為每個message消息結構體生成的Java類中,包含了一個POJO類、一個Builder類。
構造POJO消息,首先需要使用POJO類的newBuilder靜態方法獲得一個Builder構造者。每一個POJO字段的值,需要通過Builder構造者的setter方法去設置。注意,消息POJO對象并沒有setter方法。字段值設置完成之后,使用構造者的build()方法構造出POJO消息對象。

2.序列化serialization & 反序列化Deserialization的方式

一 獲得消息POJO的實例之后,可以通過多種方法將POJO對象序列化成二進制字節,或者反序列化。下面是方式一:

package com.crazymakercircle.netty.protocol; //... public class ProtobufDemo { //第1種方式:序列化 serialization &反序列化 Deserialization@Testpublic void serAndDesr1() throws IOException {MsgProtos.Msg message = buildMsg();//將Protobuf對象序列化成二進制字節數組byte[] data = message.toByteArray();//可以用于網絡傳輸,保存到內存或外存ByteArrayOutputStreamoutputStream = new ByteArrayOutputStream();outputStream.write(data);data = outputStream.toByteArray();//二進制字節數組反序列化成Protobuf對象MsgProtos.MsginMsg = MsgProtos.Msg.parseFrom(data);Logger.info("id:=" + inMsg.getId());Logger.info("content:=" + inMsg.getContent());} //…. }

這種方式通過調用POJO對象的toByteArray()方法將POJO對象序列化成字節數組。通過調用parseFrom(byte[] data)方法,Protobuf也可以從字節數組中重新反序列化得到POJO新的實例。

3.序列化serialization & 反序列化Deserialization的方式二

package com.crazymakercircle.netty.protocol; //... public class ProtobufDemo {//…//第2種方式:序列化 serialization &反序列化 Deserialization@Testpublic void serAndDesr2() throws IOException {MsgProtos.Msg message = buildMsg();//序列化到二進制碼流ByteArrayOutputStreamoutputStream = new ByteArrayOutputStream();message.writeTo(outputStream);ByteArrayInputStreaminputStream =new ByteArrayInputStream(outputStream.toByteArray());//從二進碼流反序列化成Protobuf對象MsgProtos.MsginMsg = MsgProtos.Msg.parseFrom(inputStream);Logger.info("id:=" + inMsg.getId());Logger.info("content:=" + inMsg.getContent());} //…. }

這種方式通過調用POJO對象的writeTo(OutputStream)方法將POJO對象的二進制字節寫出到輸出流。通過調用parseFrom(InputStream)方法,Protobuf從輸入流中讀取二進制碼流重新反序列化,得到POJO新的實例。 在阻塞式的二進制碼流傳輸應用場景中,這種序列化和反序列化的方式是沒有問題的。例如,可以將二進制碼流寫入阻塞式的Java OIO套接字或者輸出到文件。但是,這種方式在異步操作的NIO應用場景中,存在著粘包/半包的問題。

4.序列化serialization &反序列化Deserialization的方式三

package com.crazymakercircle.netty.protocol; //... public class ProtobufDemo {//… //第3種方式:序列化 serialization &反序列化 Deserialization//帶字節長度:[字節長度][字節數據],解決粘包/半包問題@Testpublic void serAndDesr3() throws IOException {MsgProtos.Msg message = buildMsg();//序列化到二進制碼流ByteArrayOutputStreamoutputStream = new ByteArrayOutputStream();message.writeDelimitedTo(outputStream);ByteArrayInputStreaminputStream = new ByteArrayInputStream(outputStream.toByteArray());//從二進碼流反序列化成Protobuf對象MsgProtos.MsginMsg = MsgProtos.Msg.parseDelimitedFrom(inputStream);Logger.info("id:=" + inMsg.getId());Logger.info("content:=" + inMsg.getContent());} }

這種方式通過調用POJO對象的writeDelimitedTo(OutputStream)方法在序列化的字節碼之前添加了字節數組的長度。這一點類似于前面介紹的Head-Content協議,只不過Protobuf做了優化,長度的類型不是固定長度的int類型,而是可變長度varint32類型。 反序列化時,調用parseDelimitedFrom(InputStream)方法。Protobuf從輸入流中先讀取varint32類型的長度值,然后根據長度值讀取此消息的二進制字節,再反序列化得到POJO新的實例。 這種方式可以用于異步操作的NIO應用場景中,解決了粘包/半包的問題。

總結

以上是生活随笔為你收集整理的proto的介绍和基础使用的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。