您的位置:首页 > 编程语言 > Java开发

protobufのjava应用

2015-09-30 10:28 405 查看
转载自: http://blog.csdn.net/ajun_studio/article/details/7693056
            http://blog.csdn.net/lujinhong2/article/details/47204095
       Protocol buffers是一个用来序列化结构化数据的技术,支持多种语言诸如C++、Java以及Python语言,可以使用该技术来持久化数据或者序列化成网络传输的数据。相比较一些其他的XML技术而言,该技术的一个明显特点就是更加节省空间(以二进制流存储)、速度更快以及更加灵活。目前被大量用于hadoop的RPC通信协议中,所有的RPC函数参数均是使用protobuf定义的。

1.创建.proto文件

package com.zero.proto;
option java_package = "com.zero.proto";
option java_outer_classname = "AddressBookProtos";

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 AddressBook {
repeated Person person = 1;
}
proto文件说明: 

  (1)package用于指明命名空间,以防与其它项目冲突。一般可以不写。

  (2)如果指定java_package,则它作为下一步要生成的java类的package,否则package中定义的值将作为java类的package。即java类所在的包为com.zero.proto。 

  (3)java_outer_classname指定了生成的java类的类名,如果没指定,则使用.proto文件的文件名作为类名。

  (4)message表示消息定义,消息之间可以互相嵌套或者调用。 

  (5)每个字段必须使用以下3个修饰符之一:required, optional, repeated。
required:一个格式良好的消息一定要含有1个这种字段。表示该值是必须要设置的;
optional:消息格式中该字段可以有0个或1个值(不超过1个)
repeated:在一个格式良好的消息中,这种字段可以重复任意多次(包括0次)。重复的值的顺序会被保留。表示该值可以重复,相当于java中的List。
  (6)每个字段都有唯一的一个标识符,可以理解为索引,用于识别各个字段。

2.生成java文件

       需要protoc-2.4.1-win32.zip用于生成java文件,protobuf-java-2.4.1.jar,用户客户端调用。https://github.com/google/protobuf/tags中可以找到各个版本的上述文件。

       将.proto放到解压后的protoc-2.4.1-win32.zip里面的protoc.exe同一级目录,然后cmd cd到该目录再执行:
protoc.exe --java_out=./ msg.proto
       此时在这个目录下会生成com\zero\proto\ AddressBookProtos.java。

3.java客户端使用示例

// 序列化:
Person.Persona.Builder b = Person.Persona.newBuilder();
b.setXXX(i);
Person.Persona p = b.build();
byte [] value = p.toByteArray();

// 反序列化:
Person.Persona last = Person.Persona.parseFrom(person);
       关于一些方法的使用可参考:http://www.blogjava.net/DLevin/archive/2015/04/01/424012.aspx

4.proto type --- java type对应关系

proto类型      Java 类型           备注
double           double     
float               float     
int32              int                       使用可变长编码方式。编码负数时不够高效——如果字段可能含有负数,那么请使用sint32。
int64              long                    使用可变长编码方式。编码负数时不够高效——如果字段可能含有负数,那么请使用sint64。
uint32            int[1]                   Uses variable-length encoding.
uint64            long[1]                Uses variable-length encoding.
sint32            int                       使用可变长编码方式。有符号的整型值。编码时比通常的int32高效。
sint64            long                    使用可变长编码方式。有符号的整型值。编码时比通常的int64高效。
fixed32          int[1]                   总是4个字节。如果数值总是比总是比228大的话,这个类型会比uint32高效。
fixed64          long[1]                总是8个字节。如果数值总是比总是比256大的话,这个类型会比uint64高效。
sfixed32        int                       总是4个字节。
sfixed64        long                    总是8个字节。
bool               boolean     
string             String                  一个字符串必须是UTF-8编码或者7-bit ASCII编码的文本。
bytes             ByteString           可能包含任意顺序的字节数据。

5.proto3

Proto3的语法变化

    1. 新添加了syntax关键字,以指明proto文件的protobuf协议版本。如:syntax = "proto3";

    2. 删除required,只保留repeated。required和optional都不要了,默认就是optional;

    3. 支持map,其声明形式如下:map<key_type, value_type> map_field = N;

    4. 字段default标记废弃。

简单示例:
syntax = "proto3";

package proto3_proto;

message Message
{
enum Humour {
UNKNOWN = 0;
PUNS = 1;
SLAPSTICK = 2;
BILL_BAILEY = 3;
}

string name = 1;
Humour hilarity = 2;
uint32 height_in_cm = 3;
bytes data = 4;
int64 result_count = 7;
bool true_scotsman = 8;
float score = 9;

repeated uint64 key = 5[packed = true];
}

message MessageArray
{
map<string, Message> msg_map = 1;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: