Protobuf序列化這么強(qiáng),為什么不花五分鐘學(xué)習(xí)一下呢?
java自帶的序列化機(jī)制效率太低,有很多缺點(diǎn)。因此涌現(xiàn)出了很多優(yōu)秀的系列化框架,比如說(shuō)protobuf、protostuff、thrift、hession、kryo、avro、fst、msgpack等等。這篇文章我們就看一下protobuf,給出一個(gè)簡(jiǎn)單案例,看看其是如何實(shí)現(xiàn)的。
注:若你對(duì)序列化概念和基本使用還有疑惑,可以翻看我之前的文章,或者百度一些基本概念和作用。
一、為什么要使用protobuf?
使用protobuf的原因肯定是為了解決開發(fā)中的一些問題,那使用其他的序列化機(jī)制會(huì)出現(xiàn)什么問題呢?
(1)java默認(rèn)序列化機(jī)制:效率極低,而且還能不能跨語(yǔ)言之間共享數(shù)據(jù)。
(2)XML常用于與其他項(xiàng)目之間數(shù)據(jù)傳輸或者是共享數(shù)據(jù),但是編碼和解碼會(huì)造成很大的性能損失。
(3)json格式也是常見的一種,但是在json在解析的時(shí)候非常耗時(shí),而且json結(jié)構(gòu)非常占內(nèi)存。
但是我們protobuf是一種靈活的、高效的、自動(dòng)化的序列化機(jī)制,可以有效的解決上面的問題。
二、如何使用protobuf
protobuf這么優(yōu)秀使用起來(lái)也是非常的簡(jiǎn)單,我們可以給出其主要的三個(gè)步驟,然后使用一個(gè)基本的案例去實(shí)現(xiàn)一下。
(1)定義.proto文件:我們?cè)谶@個(gè)文件中描述我們序列化的信息,類似于bean類。
(2)根據(jù).proto生成對(duì)應(yīng)的類文件,上面這個(gè)proto就像是一個(gè)模板,現(xiàn)在我們要根據(jù)這個(gè)模板創(chuàng)建出一個(gè)java類。
(3)序列化。
有了這個(gè)基本的步驟我們我們就具體去實(shí)現(xiàn)一下:
1、下載安裝protobuf
第一步:下載解壓
我的電腦是windows10,因此這里給出在windows下的使用,linux下面使用我也將在后續(xù)文章推出。我們首先下載protobuf(github上搜索protobuf,有各種語(yǔ)言可供選擇)。選擇protoc-3.9.0-win64.zip。下載完成之后解壓到D:/protobuf目錄下面就好了。
第二步:配置環(huán)境變量
也就是將D:\protobuf\protoc-3.9.0-win64\bin配置到path環(huán)境變量里面。
第三步:驗(yàn)證是否安裝成功
最后我們可以在cmd中輸入protoc --version驗(yàn)證一下,是否成功。
OK,到這里我們就安裝好了。
2、編寫proto文件
之前我們說(shuō)過proto 文件非常類似java的bean。在這里我們?cè)赽in目錄下新建一個(gè)Person.proto文件(和proto.exe)。輸入下列內(nèi)容:
- syntax="proto3";
- option java_package = "com.fdd.protobuf";
- option java_outer_classname = "PersonProto";
- message Person {
- string name = 1;
- int32 age = 2;
- }
我們解釋一些我們都寫了什么
(1)第一行有一個(gè)proto3,他表示的是protobuf的語(yǔ)法版本,就類似于jdk1.7和jdk1.8的概念。需要在第一行指定。默認(rèn)使用的是proto2。
(2)java_package:表示的是java包,不指定就使用 package.生成的類會(huì)放到該package下。這里表示把生成的類存放在com.fdd.protobuf包下面。
(3)java_outer_classname:我們說(shuō)過.proto文件,要生成對(duì)應(yīng)的類,這個(gè)參數(shù)就指定輸出什么類名。這里表示生成的類名是PersonProto。
(4)message 是用于數(shù)據(jù)格式定義.
- 一個(gè) .proto 文件中可以定義多個(gè) message
- message 中定義的字段支持 string、byte、bool、map、enum、數(shù)字類型和用戶自定義的 message
- 定義字段后面需要指定唯一的標(biāo)識(shí)數(shù)字,這些數(shù)字用于識(shí)別二進(jìn)制格式 message 中的字段,一旦開始使用這個(gè) message,那么標(biāo)識(shí)數(shù)字就不能改變
- 如果需要定義 List,則在字段前加repeated即可.
- 如果已經(jīng)使用過該 message 生成的類后,想要增加字段直接新增即可.當(dāng)新增字段的類解析老數(shù)據(jù)時(shí),會(huì)將新字段置為默認(rèn)值.當(dāng)舊的類解析新數(shù)據(jù)時(shí)會(huì)忽視掉新增字段.
比如說(shuō)這里我們就定義一個(gè)復(fù)雜的proto文件:
- syntax = "proto3";
- option java_package = "com.fdd.protobuf";
- option java_outer_classname = "Persons";
- message Staff {
- int32 id = 1;
- string name = 2;
- int32 age = 3;
- // 枚舉示例
- enum PhoneType {
- MOBILE = 0;
- TELEPHONE = 1;
- }
- // 嵌套示例
- message PhoneNumber {
- string number = 1;
- PhoneType type = 2;
- }
- // list示例
- repeated PhoneNumber phone = 4;
- message Map {
- string key = 1;
- int32 value = 2;
- }
- // map示例
- Map map = 5;
- }
由于這里只是展示一個(gè)基本案例,對(duì)于其他的數(shù)據(jù)類型可以根據(jù)自己的需要定義即可。
3、根據(jù)proto文件生成class類文件
編譯起來(lái)很簡(jiǎn)單,在我們下載好的protobuf下面有一個(gè)bin目錄,里面有一個(gè)proto.exe。我們就使用這個(gè)去編譯person.proto文件就好。
也就是執(zhí)行proto.exe --java_out = / Person.proto就會(huì)編譯成功。
4、使用class類文件
上面意味著我們已經(jīng)做好了序列化的準(zhǔn)備工作,接下來(lái)我們就可以直接使用這個(gè)類了。
(1)第一步:將生成的PersonProto類引入到我們的IDEA或者是eclipse中。
(2)第二步:在idea或者是eclipse添加protobuf的依賴。
- <dependency>
- <groupId>com.google.protobuf</groupId>
- <artifactId>protobuf-java</artifactId>
- <version>3.9.0</version>
- </dependency>
(3)第三步:使用
首先看一些如何序列化:
- //1、 創(chuàng)建Builder
- PersonProto.Person.Builder builder = PersonProto.Person.newBuilder();
- //2、 設(shè)置Person的屬性
- builder.setAge(20);
- builder.setName("java的架構(gòu)師技術(shù)棧");
- //3、 創(chuàng)建Person
- PersonProto.Person person = builder.build();
- //4、序列化
- byte[] data = person.toByteArray();
- //5、將data保存在本地或者是傳到網(wǎng)絡(luò)
然后反序列化
- try {
- //一行代碼實(shí)現(xiàn)反序列化,data可以是本地?cái)?shù)據(jù)或者是網(wǎng)絡(luò)數(shù)據(jù)
- PersonProto.Person person = PersonProto.Person.parseFrom(data);
- System.out.println(person.getAge());
- System.out.println(person.getName());
- } catch (InvalidProtocolBufferException e) {
- e.printStackTrace();
- }
OK,基本的使用流程就是這。
總結(jié)
基本上就是我們定義好proto文件,然后使用proto.exe編譯成類文件,最后導(dǎo)入這個(gè)類和依賴就可以直接使用了。當(dāng)然這只是一個(gè)最簡(jiǎn)單不過的代碼,可以把這篇教程當(dāng)成一個(gè)簡(jiǎn)單的使用教程。
本文轉(zhuǎn)載自微信公眾號(hào)「愚公要移山」,作者馮冬冬。轉(zhuǎn)載本文請(qǐng)聯(lián)系愚公要移山公眾號(hào)。