IDEA下使用protobuf2(java)

一、介绍
Google提供一个具有高效的协议数据交换格式工具库(类似Json),但相比于Json,Protobuf有更高的转化效率,时间效率和空间效率都是JSON的3-5倍。google 提供了三种语言的实现:java、c++ 和 python,每一种实现都包含了相应语言的编译器以及库文件。
二、特点
Xml、Json是目前常用的数据交换格式,它们直接使用字段名称维护序列化后类实例中字段与数据之间的映射关系,一般用字符串的形式保存在序列化后的字节流中。消息和消息的定义相对独立,可读性较好。但序列化后的数据字节很大,序列化和反序列化的时间较长,数据传输效率不高。
Protobuf和Xml、Json序列化的方式不同,采用了二进制字节的序列化方式,用字段索引和字段类型通过算法计算得到字段之前的关系映射,从而达到更高的时间效率和空间效率,特别适合对数据大小和传输速率比较敏感的场合使用。
三、结构
proto文件定义了协议数据中的实体结构(message ,field)。
举例如下:
//要生成的类Person
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;
}
(1)关键字message: 代表了实体结构,由多个消息字段(field)组成。
Message中定义的全部属性在class中全部为private的。
Message的嵌套使用可以嵌套定义,也可以采用先定义再使用的方式。
(2)消息字段field: 即属性,包括字段规则+数据类型+字段名+属性顺序号+[默认值]。
数据类型:常见的原子类型都支持

字段规则:
- required:对于required的字段而言,必须初始化字段,否则会抛异常
- optional:可选字段,可以不必初始化。如果没初始化,那么将赋予该字段编号一个默认值。int或者char数据类型默认为0,string默认为"",bool默认为false,嵌套message默认为构造,枚举则为第一个。
- repeated:数据可以重复(相当于java 中的Array或List)
字段唯一标识:序列化和反序列化将会使用到。比如上面的=1; =2;
默认值:在定义消息字段时可以给出默认值。比如 [default = HOME]
四、选择版本
syntax 声明可以选择protobuf的编译器版本(v2和v3)
- syntax="proto2":选择2版本,各个字段必须明确标注编号以确定序列化后二进制数据字段的位置
- syntax="proto3":选择3版本,没有强制使用字段编号,proto3 已舍弃 required 字段,optional 字段也无法显示使用
五、Intellij IDEA中使用Protobuf
1、下载个protoc.exe
- 官网下载地址:http://code.google.com/p/protobuf/downloads/list
- protoc的源码和各个系统的预编译包:https://github.com/protocolbuffers/protobuf/releases
在里面下载个protobuf-java-3.7.1.zip,解压后bin里面有protoc.exe,下载完以后放到项目的resource\proto下。
2、编辑个.proto文件
在proto文件下创建一个AddressBook.proto。用的是proto2版本
里面的结构就是 AddressBook下有很多个Person。
每个Person必须有一个name、必须有一个id、可选有email、很多个PhoneNumber。
每个PhoneNumber必须有一个number、可选PhoneType。
PhoneType取值必为0或1或2

写的内容举例如下:
syntax = "proto2";
//生成的类会放在protoc.exe同目录下的tutorial
//如果.proto文件中写了java_package,就以java_package为准。
package beans;
//生成的类会放在protoc.exe同目录下的com.proto.tutorial下
//option java_package = "com.proto.tutorial";
//最终成的类名
//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;
package tutorial;
option java_package = "com.proto.tutorial";
option java_outer_classname = "AddressBookProtos";
message Person {
required string name = 1;
required int32 id = 2; // Unique ID number for this person.
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;
}
3、将.proto文件转成Java类
控制台中执行protoc命令,依次将.proto文件转成Java类
protoc.exe -I=F:/workspace/proto-test/src/main/resources/proto --java_out=F:/workspace/proto-test/src/main/java/beans F:/workspace/proto-test/src/main/res
ources/proto/AddressBook.proto
protoc.exe -I=(proto文件所在绝对路径,不包括proto文件本身) --java_out=(文件输出目录) (proto文件所在绝对路径,包括proto文件名)
4、相关包
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>3.7.1</version>
</dependency>
<dependency>
<groupId>com.googlecode.protobuf-java-format</groupId>
<artifactId>protobuf-java-format</artifactId>
<version>1.2</version>
</dependency>
5、.proto文件语法高亮显示
需要安装Protobuf Support插件,
依次点击Intellij中的“File”-->"Settings"-->"Plugins"-->"Browse repositories",
输入Protobuf,点击install
6、具体使用举例
AddressBookProtos.AddressBook .Builder addressBook= AddressBookProtos.AddressBook .newBuilder();
AddressBookProtos.Person .Builder person= AddressBookProtos.Person .newBuilder();
person.setName("Mike");
addressBook.setPerson(person);
IDEA下使用protobuf2(java)的更多相关文章
- gen目录无法更新,或者gen目录下的R.JAVA文件无法生成
gen目录无法更新,或者gen目录下的R.JAVA文件无法生成 1.gen目录的用处 android gen目录下的R.java并不是由用户创建,而是android工程本身将android的资源进行自 ...
- Ubuntu下安装了java但启动eclipse报错说没装java
参考资料:http://blog.csdn.net/happyteafriends/article/details/8290950 一.问题 在Ubuntu下安装了java并在~/.bashrc配置了 ...
- 不错的linux下通用的java程序启动脚本
不错的linux下通用的java程序启动脚本(转载) 虽然写起动shell的频率非常不高...但是每次要写都要对付一大堆的jar文件路径,新加jar包也必须要修改起动shell. 在网上找到一个挺好的 ...
- DOS命令下输入:java Hello 出现以下几种结果可能的原因:
DOS命令下输入:java Hello 出现以下结果:Bad command or the file name 没有这个命令或文件名 原因可能是没有成功安装jdk或者没有配置好jdk 的环境变量,或者 ...
- 使用 NIO.2 遍历目录下所有的Java文件
package wellGrounded; import java.io.IOException; import java.nio.file.FileVisitResult; import java. ...
- Ubuntu 下安装 Oracle Java
这只是一篇流水帐,记录如何安装Java. 在Ubuntu 下管理软件很方便,但安装的Java是opensdk.如果在某些条件下,需要安装Sun (Oracle)的Java,则需要自己手工安装. 一般情 ...
- ubuntu14.04 下手动安装java jdk
ubuntu14.04 下手动安装java jdk 第一步: 下载jdk.tar.gz (这里假设下载的文件名为jdk.tar.gz) 第二步: 解压 sudo tar -zxvf ./jdk.tar ...
- 【linux】linux下准确查询正在tomcat下运行的java进程。准确获取正在运行的java进程的PID
准确获取定位到tomcat下正在运行的java进程的PID命令: ps -ef|grep java | grep catalina | awk '{print $2}' 准确定位到tomcat下正在运 ...
- 【Hadoop】HA 场景下访问 HDFS JAVA API Client
客户端需要指定ns名称,节点配置,ConfiguredFailoverProxyProvider等信息. 代码示例: package cn.itacst.hadoop.hdfs; import jav ...
随机推荐
- 详解nginx.conf文件配置项(包括负载均衡)
http://www.cnblogs.com/hsapphire/archive/2010/04/08/1707109.html #运行用户 user nobody nobody; #启动进程 wo ...
- SEO 第七章
SEO第七章 网站网址链接 路径优化 网站的网址路径分为相对路径和绝对路径 绝对路径:绝对路径是完整的路径,不仅可以在站内打开,去其他地方依然可以打开. 相对路径:不是一个完整的路径,这种路径只能在站 ...
- 2019年今日头条机试_JAVA后台岗_第一题
广度优先遍历: import java.util.LinkedList; import java.util.Queue; import java.util.Scanner; class Nod ...
- Django 路由 —— Djangon如何处理一个请求
Django URL路由概述 一个干净优雅的URL方案是高质量Web应用程序中的一个重要细则Django可以让你设计URL,无论你想要什么,没有框剪限制要为应用程序设计URL,您可以非正式地创建一个名 ...
- uva 1451 数形结合
思路:枚举点t,寻找满足条件的点t': 计sum[i]为前i项合,平均值即为sum[t]-sum[t'-1]/t-t'+1 设(Pi=(i,Si),表示点在s中的位置,那么就可以画出坐标图,问题就转化 ...
- 浅谈p值(p-value是什么)
当我们说到p-value时,我们在说什么? “这个变量的p-value小于0.05,所以这个变量很重要” ........ 你真的知道自己在说什么么???这个p-value到底是个什么鬼?为什么小于0 ...
- render_to_response()
render_to_response('模板名称',字典) 字典:第二个参数必须是为该模板创建context时所使用的字典,如果不提供第二个参数,render_response()使用一个空字典
- ES6 export default 和 export 的区别
export default 和 export 区别: 1.export与export default均可用于导出常量.函数.文件.模块等 2.你可以在其它文件或模块中通过import+(常量 | 函 ...
- nodejs实现网站数据的爬取
// 引入https模块,由于我们爬取的网站采用的是https协议 const https = require('https'); // 引入cheerio模块,使用这个模块可以将爬取的网页源代码进行 ...
- [CF] 948A Protect Sheep
A. Protect Sheep time limit per test1 second memory limit per test256 megabytes inputstandard input ...