前言

之前在写Netty的时候,说过要写一篇关于PB的应用,所以现在兑现承诺。在应用的过程中,发现了很多问题,本文主要介绍两个最关键的问题。

PB如何与java项目融合,自动刷新编译,以及pb文件如何与其他项目共用,互不影响。

java中如何实现pb的Extension

概述

ProtocolBuff 是 google 提出的的一种数据交换格式,跨语言,跨平台,可扩展。基于这种特性广泛的用于网络数据通信。目前支持的语言有很多,如下:

java pb开发 pb调用java class_jar

maven项目集成Java
这里我们主要介绍在一个工程化的项目中如何集成PB,实现PB自动化刷新编译(使用mvn package指令编译),这里我们将引入一个插件protoc-jar-maven-plugin。
在pom.xml中加入插件
com.github.os72
protoc-jar-maven-plugin
3.4.0
generate-sources
run
2.6.1
true
../proto
src/main/java

重点说明一下配置 configuration

protocVersion:protoc支持的版本,这个需要各端统一。

inputDirectories:pb文件所在的目录,我这里设置成项目工程外的一个目录,目的是为了和其他工程公用一套pb文件

outputTargets:pb文件编译后生产的java文件放置的位置,这里我是放置 src/main/java下,之后你就可以在项目中自由引用。

这样就ok了,在编译maven项目时,你的所有pb文件会跟着自动编译,而且还能和好的与其他工程无缝衔接,免去手动各种烦恼。

PB在java项目中的实战

这里主要说明Extension的问题,对于简单的pb就不做阐述。废话不说直接上代码。

PB文件格式
基础pb文件 Base.proto,所有的extension的pb文件都会import这个文件。
package proto;
// 包格式
message PBDemo
{
oneof body {
TestDemoRequest testdemo_req = 1;
TestDemoResponse testdemo_rsp = 2;
}
}
message TestDemoRequest
{
extensions 100 to max;
}
message TestDemoResponse
{
extensions 100 to max;
}
扩展协议文件 testdemo.proto
package proto.testdemo;
import "base.proto";
extend TestDemoRequest
{
optional HelloRequest hello_req = 101;
}
extend TestDemoResponse
{
optional HelloResponse hello_rsp = 101;
}
message HelloRequest
{
optional string message = 1;
}
message HelloResponse
{
optional string message = 1;
}
这样的一个pb结构是我们在数据通信中经常使用的,结构,与业务扩展性上都非常好。接下来我们看看,在java中如何对这个解包,和打包。
打包示例
// 打第一个message
Testdemo.HelloRequest.Builder reqBuilder = Testdemo.HelloRequest.newBuilder();
reqBuilder.setMessage(msg);
Testdemo.HelloRequest req = reqBuilder.build();
// 打extension
Base.TestDemoRequest.Builder testBuilder = Base.TestDemoRequest.newBuilder();
testBuilder.setExtension(helloReq, req);
// 打最外层的message
Base.PBDemo.Builder baseBuilder = Base.PBDemo.newBuilder();
Base.PBDemo pbDemo = baseBuilder.setTestdemoReq(testBuilder.build()).build();
byte[] packet = pbDemo.toByteArray();
ByteBuf buf = Unpooled.buffer();
buf.writeBytes(packet);
// 发送数据包
channel.writeAndFlush(buf);
解包示例
ByteBuf buf = (ByteBuf)msg;
byte[] packet = new byte[buf.readableBytes()];
buf.readBytes(packet);
ExtensionRegistry registry = ExtensionRegistry.newInstance();
Testdemo.registerAllExtensions(registry);
Base.PBDemo pbdemo = Base.PBDemo.parseFrom(packet, registry);
Testdemo.HelloResponse rsp = pbdemo.getTestdemoRsp().getExtension(Testdemo.helloRsp);
System.out.println(rsp.getMessage().toString());

总结

PB的打包解包性能,介于二进制和json之间,同时协议的扩展性,以及数据包压缩功能, 独立于语言和平台特性,都足以让其脱颖而出。


java pb开发 pb调用java class_jar