【Windows】
1.准备两个文件proto.exe,protobuf-java-2.5.0.jar。
如果是protobuf-2.5.0.zip,将其解压缩后,用VS2010打开其中的vsprojects工程,编译后,将proto.exe拷贝待用。
2.建立一个Java工程test-protocbuf
将proto.exe拷贝至test-protocbuf下;
工程下建立proto文件夹,用来存放xxx.proto文件;
编写规范的proto文件兵存储至proto文件夹下;
生成Java文件,使用cmd命令编译这个proto文件:
在protc.exe目录下执行protoc --version可查看protoc版本;
在protc.exe目录下执行protoc --java_out=./src ./proto/xxx.proto;
在指定目录下将生成一个Java文件,将其引入到MyEclipse中;
再把protobuf-java-2.5.0.jar引入到工程libs目录中;
package com.leehongee.netserver.net.bean; option java_package = "com.leehongee.netserver.net.bean"; option java_outer_classname = "Request"; message request_Net { required string cmd = 1; optional int32 keycode = 2; optional sint32 posX = 3; optional sint32 posY = 4; optional bool onOrOff = 5; optional bool ontouch = 6; }
3.使用方法调用序列化:
Request .request_Net .Builder builder=Request .request_Net ..newBuilder();
builder.setCmd("ontouch");
Request .request_Net request=builder.builder();
byte[] buffer=request.toByteAarray();
4.使用反序列化
try{
Request .request_Net request = Request .request_Net .parseFrom(buffer);
}
catch(Exception ex){
System.out.println(ex.getMessage());
}
例:编写msg.proto文件
为需要序列化的数据接口加入一个message属性,为每一个字段指定名称和类型。注意message 的名称不能与java_outer_classname 名称相同,不然编译不过。
option java_package = "com.protobuftest.protobuf";
option java_outer_classname = "PersonProbuf";
message Person {
required string name = 1;
required int32 id = 2;
optional string email = 3;
enum PhoneType {
MOBILE = 0;
HOME = 1;
WORK = 2;
}
message PhoneNumber {
required string number = 1;
optional PhoneType type = 2 [default = HOME];
}
repeated PhoneNumber phone = 4;
message CountryInfo {
required string name = 1;
required string code = 2;
optional int32 number = 3;
}
}
message AddressBook {
repeated Person person = 1;
}
4.进行测试
import java.util.List;
import com.google.protobuf.InvalidProtocolBufferException;
import com.protobuftest.protobuf.PersonProbuf;
import com.protobuftest.protobuf.PersonProbuf.Person;
import com.protobuftest.protobuf.PersonProbuf.Person.PhoneNumber;
public class TestPb {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
PersonProbuf.Person.Builder builder = PersonProbuf.Person.newBuilder();
builder.setEmail("kkk@email.com");
builder.setId(1);
builder.setName("TestName");
builder.addPhone(PersonProbuf.Person.PhoneNumber.newBuilder().setNumber("131111111").setType(PersonProbuf.Person.PhoneType.MOBILE));
builder.addPhone(PersonProbuf.Person.PhoneNumber.newBuilder().setNumber("011111").setType(PersonProbuf.Person.PhoneType.HOME));
Person person = builder.build();
byte[] buf = person.toByteArray();
try {
Person person2 = PersonProbuf.Person.parseFrom(buf);
System.out.println(person2.getName() + ", " + person2.getEmail());
List<PhoneNumber> lstPhones = person2.getPhoneList();
for (PhoneNumber phoneNumber : lstPhones) {
System.out.println(phoneNumber.getNumber());
}
} catch (InvalidProtocolBufferException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(buf);
}
}
***********************************************
工程文件结构:
【理论知识点】
全称是Protocol Buffers,是Google内部用的一种高效的、可扩展的对结构化数据进行编码的格式规范,Google内部很多程序间的通信协议都用了protobuf。是用于结构化数据串行化的灵活、高效、自动的方法,有如XML,不过它更小、更快、也更简单。你可以定义自己的数据结构,然后使用代码生成器生成的代码来读写这个数据结构。你甚至可以在无需重新部署程序的情况下更新数据结构。
用于序列和反序列所有基于Google Protobuf格式的各种消息。 能够将protobuf格式还原成XML、JSON和HTML等文本格式。
将对象转成二进制数据进行传输,缺点是可读性差,但是占用空间小,有时候采用protobuf来摒弃传统的XML传输数据。
google官方连接地址 http://code.google.com/p/protobuf/downloads/list
选择proto.exe压缩包protoc-2.5.0.zip和protobuf-java-2.5.0.jar压缩包protobuf-2.5.0.zip
下载一个protobuf-java-2.5.0.jar文件(注意,要与你刚才下的proto.exe版本相同,否则可能出现编译通不过现象)
备注:限定修饰符 required ,optional ,repeated
required: 表示是一个必须字段,必须相对于发送方,在发送消息之前必须设置该字段的值,对于接收方,必须能够识别该字段的意思。
optional:表示是一个可选字段,可选对于发送方,在发送消息时,可以有选择性的设置或者不设置该字段的值。
repeated:表示该字段可以包含0~N个元素。其特性和optional一样,但是每一次可以包含多个值。
【摘录】
一条消息数据,用protobuf序列化后的大小是json的10分之一,xml格式的20分之一,是二进制序列化的10分之一,总体看来ProtoBuf的优势还是很明显的
protobuf是google提供的一个开源序列化框架,类似于XML,JSON这样的数据表示语言,详情访问protobuf的google官方网站
protobuf在google中是一个比较核心的基础库,作为分布式运算涉及到大量的不同业务消息的传递,如何高效简洁的表示、操作这些业务消息在google这样的大规模应用中是至关重要的。而protobuf这样的库正好是在效率、数据大小、易用性之间取得了很好的平衡。
protobuf简单总结如下几点:
- 灵活(方便接口更新)、高效(效率经过google的优化,传输效率比普通的XML等高很多);
- 易于使用;开发人员通过按照一定的语法定义结构化的消息格式,然后送给命令行工具,工具将自动生成相关的类,可以支持java、c++、python等语言环境。通过将这些类包含在项目中,可以很轻松的调用相关方法来完成业务消息的序列化与反序列化工作。
- 多语言支持;原生支持c++,java,python
个人总结的适用protobuf的场合:
- 需要和其它系统做消息交换的,对消息大小很敏感的。那么protobuf适合了,它语言无关,消息空间相对xml和json等节省很多。
- 小数据的场合。如果你是大数据,用它并不适合。
- 项目语言是c++,java,python的,因为它们可以使用google的源生类库,序列化和反序列化的效率非常高。其它的语言需要第三方或者自己写,序列化和反序列化的效率不保证。
- 总体而言,protobuf还是非常好用的,被很多开源系统用于数据通信的工具,在google也是核心的基础库。
此外,还有更牛叉的facebook的thrift,2007年由Facebook开发,之后在2008年加到Apache计划中。是一个跨语言的轻量级RPC消息和数据交换框架,Thrift能生成的语言有: C++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, Smalltalk, and OCaml,这是它的一大优点。