十年網(wǎng)站開發(fā)經(jīng)驗(yàn) + 多家企業(yè)客戶 + 靠譜的建站團(tuán)隊(duì)
量身定制 + 運(yùn)營(yíng)維護(hù)+專業(yè)推廣+無(wú)憂售后,網(wǎng)站問(wèn)題一站解決
protobuf
(protocol buffer) 是谷歌內(nèi)部的混合語(yǔ)言數(shù)據(jù)標(biāo)準(zhǔn)。通過(guò)將結(jié)構(gòu)化的數(shù)據(jù)進(jìn)行序列化(串行化),用于通訊協(xié)議、數(shù)據(jù)存儲(chǔ)等領(lǐng)域的語(yǔ)言無(wú)關(guān)、平臺(tái)無(wú)關(guān)、可擴(kuò)展的序列化結(jié)構(gòu)數(shù)據(jù)格式。通常說(shuō)的protobuf包括以下三點(diǎn):
message
:protobuf
中定義一個(gè)消息類型是通過(guò)關(guān)鍵字message
字段指定的,這個(gè)關(guān)鍵字類似于C++/Java中的class關(guān)鍵字。使用protobuf編譯器將proto
編譯成C++代碼之后,每個(gè)message
都會(huì)生成一個(gè)名字與之對(duì)應(yīng)的C++類,該類公開繼承自google::protobuf::Message
創(chuàng)建turorial.person.proto 文件,文件內(nèi)容如下:
// FileName: tutorial.person.proto // 通常文件名建議命名格式為 包名.消息名.proto // 表示正在使用proto2命令 syntax = "proto2"; //包聲明,tutorial 也可以聲明為二級(jí)類型。 //例如a.b,表示a類別下b子類別 package tutorial; //編譯器將生成一個(gè)名為person的類 //類的字段信息包括姓名name,編號(hào)id,郵箱email, //以及電話號(hào)碼phones message Person { required string name = 1;? // (位置1) required int32 id = 2;? optional string email = 3;? // (位置2) enum PhoneType {? //電話類型枚舉值 MOBILE = 0;? //手機(jī)號(hào)? HOME = 1;??? //家庭聯(lián)系電話 WORK = 2;??? //工作聯(lián)系電話 } //電話號(hào)碼phone消息體 //組成包括號(hào)碼number、電話類型 type message PhoneNumber { required string number = 1;??? optional PhoneType type = 2 [default = HOME]; // (位置3) }? repeated PhoneNumber phones = 4; // (位置4) } // 通訊錄消息體,包括一個(gè)Person類的people message AddressBook { repeated Person people = 1; } |
字段解釋:
包聲明
proto
文件以package
聲明開頭,這有助于防止不同項(xiàng)目之間命名沖突。在C++中,以package
聲明的文件內(nèi)容生成的類將放在與包名匹配的namespace
中,上面的.proto
文件中所有的聲明都屬于tutorial
。
標(biāo)識(shí)符:
protobuf協(xié)議的標(biāo)識(shí)符為message或enum,如示例中的Person和PhoneType。message標(biāo)識(shí)一條消息,enum標(biāo)識(shí)一個(gè)枚舉類型。使用protobuf編譯器將協(xié)議文件編譯后,message和enum都會(huì)生成一個(gè)類
字段規(guī)則
·? repeated: 消息體中可重復(fù)字段,重復(fù)的值的順序會(huì)被保留(例如位置3)。其中,proto3默認(rèn)使用packed方式存儲(chǔ),這樣編碼方式比較節(jié)省內(nèi)存。
標(biāo)識(shí)號(hào)
標(biāo)識(shí)號(hào)
:在消息體的定義中,每個(gè)字段都必須要有一個(gè)唯一的標(biāo)識(shí)號(hào),標(biāo)識(shí)號(hào)是[0,2^29-1]范圍內(nèi)的一個(gè)整數(shù)。以Person為例,name=1,id=2, email=3, phones=4 中的1-4就是標(biāo)識(shí)號(hào)。
數(shù)據(jù)定義
許多標(biāo)準(zhǔn)的簡(jiǎn)單數(shù)據(jù)類型都可以用作message
字段類型,包括bool
,int32
,float
,double
和string
。還可以使用其他message
類型作為字段類型在消息體中添加更多結(jié)構(gòu)。在上面的示例中,Person
包含PhoneNumber message
, 而AddressBook
包含Person message
。甚至可以定義嵌套在其他message中的message類型。例如,上面的PhoneNumber
定義在Person
。
以下是示例中用到的proto文件teacher.proto:
syntax = "proto3"; package space; message course{ // 課程名稱 string name = 1; // 課程分?jǐn)?shù) int32 score = 2; } message student{ // 學(xué)生名稱 string name = 1; // 學(xué)生年齡 int32 age = 2; // 學(xué)生所修課程,可能是多門,是一組數(shù)組 repeated course course = 3; } |
從Release Protocol Buffers v3.5.1 · protocolbuffers/protobuf · GitHub 下載protoc工具,此工具可以根據(jù)proto文件生成java類。
下載完成后,解壓縮該文件。
打開cmd命令窗口,跳轉(zhuǎn)至解壓縮路徑:
執(zhí)行以下命令:
protoc.exe --java_out=src/main/java/ teacher.proto |
執(zhí)行此命令前,需要在新建文件夾目錄src/main/java
執(zhí)行成功后,可以看到在src/main/java 下生成的java類文件Teacher.java。
新建一個(gè)maven工程,并導(dǎo)入以下pom依賴
protobuf-java protobuf-java-util ?? grpc-all ?? os-maven-plugin protobuf-maven-plugin ???? ???????? com.google.protobuf:protoc:3.1.0:exe:${os.detected.classifier} ???? ???? ???? ???????? io.grpc:protoc-gen-grpc-java:1.11.0:exe:${os.detected.classifier} ???? ???? ???????? ???????????? ???????????? ???????? ???? |
將Teacher.java 添加至該工程。新建一個(gè)測(cè)試類TestMyProtobuf.java 進(jìn)行測(cè)試。代碼如下:
import com.google.protobuf.InvalidProtocolBufferException; import com.google.protobuf.util.JsonFormat; import space.Teacher; import java.util.Arrays; public class TestMyProtobuf { public static void main(String[] args) { // 生成課程1對(duì)象 Teacher.course.Builder courseBuilder1 = Teacher.course.newBuilder(); courseBuilder1.setName("Java"); courseBuilder1.setScore(99); Teacher.course course1 = courseBuilder1.build(); // 生成課程2對(duì)象 Teacher.course.Builder courseBuilder2 = Teacher.course.newBuilder(); courseBuilder2.setName("Python"); courseBuilder2.setScore(98); Teacher.course course2 = courseBuilder2.build(); // 生成學(xué)生對(duì)象 Teacher.student.Builder studentBuilder = Teacher.student.newBuilder(); studentBuilder.setName("Lucy"); studentBuilder.setAge(23); studentBuilder.addCourse(0,course1); studentBuilder.addCourse(1,course2); Teacher.student student = studentBuilder.build(); // proto對(duì)象 System.out.println("The student object is: \n" + student); // 序列化 byte[] studentByte = student.toByteArray(); System.out.println("The student after encode is:\n" + Arrays.toString(studentByte)); try { // 反序列化 Teacher.student newStudent = Teacher.student.parseFrom(studentByte); System.out.println("The student after decode is:\n" + newStudent); // 轉(zhuǎn)換json System.out.println("The student json format is:\n" + JsonFormat.printer().print(student)); } catch (InvalidProtocolBufferException e) { e.printStackTrace(); } } } |
測(cè)試結(jié)果如下:
The student object is: name: "Lucy" age: 23 course { name: "Java" score: 99 } course { name: "Python" score: 98 } The student after encode is: [10, 4, 76, 117, 99, 121, 16, 23, 26, 8, 10, 4, 74, 97, 118, 97, 16, 99, 26, 10, 10, 6, 80, 121, 116, 104, 111, 110, 16, 98] The student after decode is: name: "Lucy" age: 23 course { name: "Java" score: 99 } course { name: "Python" score: 98 } The student json format is: { "name": "Lucy", "age": 23, "course": [{ "name": "Java", "score": 99 }, { "name": "Python", "score": 98 }] } |
你是否還在尋找穩(wěn)定的海外服務(wù)器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機(jī)房具備T級(jí)流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確流量調(diào)度確保服務(wù)器高可用性,企業(yè)級(jí)服務(wù)器適合批量采購(gòu),新人活動(dòng)首月15元起,快前往官網(wǎng)查看詳情吧