protocolbuffer(以下简称PB)是google 的一种数据交换的格式,它独立于语言,独立于平台。google 提供了三种语言的实现:java、c++ 和 python,每一种实现都包含了相应语言的编译器以及库文件。由于它是一种二进制的格式,比使用 xml 进行数据交换快许多。可以把它用于分布式应用之间的数据通信或者异构环境下的数据交换。作为一种效率和兼容性都很优秀的二进制数据传输格式,可以用于诸如网络传输、配置文件、数据存储等诸多领域。---摘自百度百科。
从上面可以看出,protobuf其实是一种传输协议,这个跟thrift有很大不同。thrift是Facebook开源的一整套的RPC方案,但是它却总是被拿来跟protobuf做对比,这个有很大的误导,正确的说是,thrift里面不仅仅包含了传输协议。因此,跟protobuf相比较的应该xml或者是json。我们可以来简单的说一下,protobuf相较于xml或者json的区别,protobuf是基于将数据采用二进制来序列化的,而xml或者json则是基于文本数据的,现在高下立判,protobuf比xml或者说json更加高效和安全,而且序列化反序列化方便。
之前,看protobuf总是一副高大上的样子,让人望而生畏。最近需要写个项目,采用udp去跟另一边用.net开发的服务通讯,所以采用protobuf作为两边之间通信协议(对象序列化反序列化协议),于是就写了下demo。发觉其实非常简单,我们如果用protobuf更多的只需要关注底层的传输就OK了,剩下的序列化反序列化它其实已经说好了。
用java写最简单的protobuf只需要两件东西,一件是将proto文件(protobuf独有的用来规定各种不同语言间统一数据描述规范)转成java实体类的程序(我在windows下用protoc.exe文件,这个文件code.google.com有编译好的),另一个就是java的protobuf 实现的jar包了。
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>2.5.0</version>
</dependency>
接下来在写proto文件
package protobuf;
option java_package = "com.xxx.simpleProtobuf";
option java_outer_classname = "LogMessageProtobuf";
message LogMessage {
required int32 ID = 1;
required string Url = 2;
required string message = 3;
}
定义好了之后,需要用protoc.exe 翻译成java文件,记住protoc跟java的接口jar包的版本要一致。
在命令行运行protoc --java_out=./ LogMessageProtobuf.proto
接下来就可以在同一个目录下看到com/xxx/simpleProtobuf里面的 LogMessageProtobuf.java文件
import com.google.protobuf.InvalidProtocolBufferException;
/**
* Created by lsz on 2014/7/18.
*/
public class ProtobufDemo{
public static void main(String[] args) throws InvalidProtocolBufferException {
LogMessageProtobuf.LogMessage logMsg = LogMessageProtobuf.LogMessage.newBuilder()
.setID(1)
.setUrl("http://www.xxxx.com")
.setMessage("xxxx").build();
System.out.println(logMsg);
byte[] bs = tb.toByteArray();
LogMessageProtobuf.LogMessage logMsgFromBytes = LogMessageProtobuf.LogMessage.parseFrom(bs);
System.out.println(logMsgFromBytes);
}
}
运行成可以看到logMsg跟logMsgFromBytes的内容是一样的,根据上面的例子,我们会发现,真正保存这个对象数据的就是bs这个字节数组,没有其他的内容,那我们是不是可以通过其他途径去传输这个byte数组,让其他的地方也可以得到这个数据对象呢。