ProtoBuf介紹
ProtoBuf 是google團隊開發的用於高效存儲和讀取結構化數據的工具,google出品,必屬精品。
目前最新版本為3。文檔地址:https://developers.google.com/protocol-buffers/docs/proto3
相比於xml
,json
,protobuf
壓縮率更高,傳輸高效,自然很節省流量。
protobuf支持跨語言,貌似前后端使用java
和JavaScript
的眾多吧。
整理下java和JavaScript的例子
需要下載protoc
可執行文件。通過編寫.proto,命令生成相應的文件,比如java,js等。
編寫Person.proto。
具體語法可以查看官網,這是最基礎的一個對象。
syntax = "proto3";
option java_package = "com.dahai.protobuf";
option java_outer_classname = "PersonModel";
message Person {
int32 id = 1;
string name = 2;
int32 age = 3;
string email = 4;
}
可以通過protoc
命令生成,此處為了方便起見,使用maven plugin
來生成(原理一直,會下載相應的protoc可執行文件)
創建maven工程,在resources目錄創建proto文件夾,將示例文件Person.proto放入改文件夾下。
pom.xml引入相應依賴
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>3.11.1</version>
</dependency>
pom.xml引入相應的插件
<build>
<extensions>
<extension>
<groupId>kr.motd.maven</groupId>
<artifactId>os-maven-plugin</artifactId>
<version>1.6.2</version>
</extension>
</extensions>
<plugins>
<plugin>
<groupId>org.xolstice.maven.plugins</groupId>
<artifactId>protobuf-maven-plugin</artifactId>
<version>0.6.1</version>
<extensions>true</extensions>
<configuration>
<!--指定項目的proto文件目錄-->
<protoSourceRoot>src/main/resources/proto</protoSourceRoot>
<clearOutputDirectory>false</clearOutputDirectory>
<!--不存在會自動下載-->
<protocArtifact>
com.google.protobuf:protoc:3.11.1:exe:${os.detected.classifier}
</protocArtifact>
<pluginId>grpc-java</pluginId>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>compile-custom</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
執行標紅箭頭的命令即可生成。
將生成的文件放入相應的包下面即可
demo測試
@Test
public void test3() throws InvalidProtocolBufferException {
// 創建person對象
Person person = Person.newBuilder()
.setId(1)
.setName("陳海洋")
.setAge(18)
.setEmail("1559843332@qq.com")
.build();
System.out.println(person);
// 反序列化獲取person
byte[] bytes = person.toByteArray();
Person newPerson = Person.parseFrom(bytes);
System.out.println(newPerson);
}
使用protobuf是為了節省用戶流量,來實戰下。
java作為服務端+客戶端測試
// 暴露接口,返回二進制數據
@GetMapping("/person/{id}")
public byte[] person(@PathVariable("id") Integer id) {
Person person = Person.newBuilder()
.setId(id)
.setName("陳海洋")
.setAge(18)
.setEmail("1559843332@qq.com")
.build();
return person.toByteArray();
}
// RestTemplate客戶端測試
@Test
public void test1() throws IOException {
RestTemplate restTemplate = new RestTemplate();
String url = "http://localhost:8881/demo/person/2";
ResponseEntity<Resource> forEntity = restTemplate.getForEntity(url, Resource.class);
Person person = Person.parseFrom(forEntity.getBody().getInputStream());
System.out.println(person);
}
客戶端前端調用示例
既然是跨平台,js肯定也是可以解析二進制流的。
前端也可以通過proto文件生成相應的js。如下是js反序列化示例
為了寫前端demo,也是爬了好多坑,都是淚啊!(本想基於原生的)
import messages from '../../utils/proto/person.js'
axios({
method: 'get',
url: 'http://localhost:8881/demo/person/10',
responseType: 'arraybuffer'
}).then((res) => {
console.log('res.data', res.data)
var person = messages.Person.decode(new Uint8Array(res.data))
console.log('java', person)
console.log('java id', person.id)
}
)
這只是demo,實際項目一般不會反悔bety[]
數據。在我們的業務中是通過websocket
來傳輸的。
項目地址
https://github.com/chywx/spring-boot-chy/tree/master/chy-protobuf