Protocol Buffers介绍
Protocol Buffers(Protobuf)是Google推出的语言无关,平台无关的可扩展机制,用于序列化结构数据。由于是一种二进制的序列化协议,并且数据结构做了相应优化,因此比传统的XML、JSON数据格式序列化后体积更小,传输更快。Protobuf有proto2和proto3两个版本,有着不同的数据格式定义,在这里我们使用proto3版本。Protobuf使用了一个编译器,可根据.proto
文件中定义的数据结构,自动生成各种语言的模板代码,方便使用。
一个hello world示例程序
我们以一个hello world
的例子来尝试在Netty中使用Protobuf:编写一个GreetClient
,向服务端发送用户姓名name(如world);服务端接收到请求,在姓名name前面添加前缀hello(如name为hello,添加前缀变为hello word
),并将该消息message返回给客户端。这个例子参考了grpc官方的hello world例子。
编写helloworld.proto文件
首先我们编写一个helloworld.proto
文件,内容如下:
syntax = "proto3";
option java_multiple_files = true;
option java_package = "com.alphabc.netty.protobuf.helloworld";
option java_outer_classname = "HelloWorldProto";
option objc_class_prefix = "HLW";
package helloworld;
// The request message containing the user's name.
message HelloRequest {
string name = 1;
}
// The response message containing the greetings
message HelloReply {
string message = 1;
}
编译生成Java代码
从Protobuf的官方github release页面下载对应操作系统上需要用到的编译器文件,并解压得到protoc。
为了使用protoc将helloworld.proto
文件编译成Java代码,进入项目目录执行以下命令:
protoc --java_out=src/main/java src/main/java/com/alphabc/netty/protobuf/helloworld/helloworld.proto
最终生成的类目录结构大致如下:
src/main/java/com/alphabc/netty/protobuf/helloworld
├── HelloReply.java
├── HelloReplyOrBuilder.java
├── HelloRequest.java
├── HelloRequestOrBuilder.java
├── HelloWorldProto.java
└── helloworld.proto
由于生成的模板代码较多,此处就不贴出来了。
引入Maven依赖
引入Netty和Protobuf的Maven依赖如下:
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.1.32.Final</version>
</dependency>
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>3.11.0</version>
</dependency>
测试Protobuf的序列化和反序列化
编写Protobuf的序列化和反序列化测试类如下:
package com.alphabc.netty.protobuf;
import com.alphabc.netty.protobuf.helloworld.HelloRequest;
import com.google.protobuf.InvalidProtocolBufferException;
public class ProtobufTest {
public static void main(String[] args) throws InvalidProtocolBufferException {
HelloRequest helloRequest = HelloRequest.newBuilder().setName("Jack").build();
byte[] bytes = helloRequest.toByteArray();
HelloRequest parse = HelloRequest.parseFrom(bytes);
System.out.println(parse.toString());
System.out.println(parse.getName());
}
}
执行后控制台输出:
name: "Jack"
Jack
编写服务端和客户端代码
编写Netty服务端