赞
踩
概念
Protocol buffers are a flexible, efficient, automated mechanism for serializing structured data – think XML, but smaller, faster, and simpler
简单的说, Protobuf3是类似json,xml的数据交换协议,但是它比它们传输的数据更小,传输的速度更快; 跨语言交互,支持大部分主流编程语言
Demo
Message
Protobuf3通过proto文件定义交互的对象,基本的数据结构叫做Message。 以下是本次使用的第一个demo
// 如果使用此注释,则使用proto3; 否则使用proto2
syntax = "proto3";
// 生成类的包名
option java_package = "com.hry.spring.proto.simple";
//生成的数据访问类的类名,如果没有指定此值,则生成的类名为proto文件名的驼峰命名方法
option java_outer_classname = "FirstDemo";
message Demo {
int32 id = 1;
string name = 2;
string email = 3;
repeated int32 mylist = 4; // List列表
}1
2
3
4
5
6
7
8
9
10
11
121
2
3
4
5
6
7
8
9
10
11
12
repeated : 在Java中表示这是一个List列表
int32, string 分别对应java中的int, String
生成Java类
定义后proto,则可以通过官方的工具生成类 protoc-3.0.0-win32.zip
有两种方式生成java类
方法一通过cmd命令:
protoc参数的意义见下方的ProtoGenerateClass 类注释
D:/tool/protoc/protoc-3.0.0-win32/bin/protoc.exe -I=D:/project/git/spring_boot/protobuf --java_out=d:/tmp D:/project/git\spring_boot/protobuf/src/main/resources/com/hry/spring/proto/simple/*.proto11
方法二通过Java类来实现
封装调用window命令的类
public class Cmd {
private void writeInputStream2OutputStream(InputStream in, OutputStream out) throws IOException {
LineNumberReader lnr = new LineNumberReader(new InputStreamReader(in, "UTF-8"));
PrintWriter pw = new PrintWriter(new OutputStreamWriter(out, "UTF-8"));
String s;
while ((s = lnr.readLine()) != null) {
// 打印信息
pw.println(s);
}
// 关闭输出流
lnr.close();
pw.close();
}
public void execute(List commandList){
Assert.notNull(commandList, "commandList can't be null!");
// 如:protoc.exe -I=D:/project/git/spring_boot/protobuf --java_out=d:/tmp D:/project/git\spring_boot/protobuf/src/main/resources/com/hry/spring/proto/simple/person-entity.proto
ProcessBuilder pb = new ProcessBuilder(commandList);
// 错误流和输出流合并到一起输出,否则可能因为2个流的某个缓存区满了而导致现场阻塞
//错误和正确信息合并输出,因为输出有2个,一个是正确,一个错误,着个只要其中有1个无法被实时读取,则可能造成进程阻塞
pb.redirectErrorStream(true);
Process p;
try {
p = pb.start();
writeInputStream2OutputStream(p.getInputStream(), System.err);
} catch (IOException e) {
throw new RuntimeException(e);
}
int iResult = p.exitValue();
if(iResult == 0){
System.out.println(" result = " +p.exitValue() + " execute command success! Command = " + commandList);
}else{
System.out.println(" result = " +p.exitValue() + " execute command failure! Command = " + commandList);
}
}
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
401
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
调用cmd类
public class ProtoGenerateClass {
// protoc的目录
private static final String PROTOC_FILE = "D:/tool/protoc/protoc-3.0.0-win32/bin/protoc.exe";
// specifies a directory in which to look for .proto files when resolving import directives
private static final String IMPOR_TPROTO = "D:/project/git/spring_boot/protobuf";
// 生成java类输出目录
private static final String JAVA_OUT = "d:/tmp";
// 指定proto文件
private static final String protos = "D:/project/git/spring_boot/protobuf/src/main/resources/com/hry/spring/proto/simple/*.proto";
public static void main(String[] args) throws IOException {
List lCommand = new ArrayList();
lCommand.add(PROTOC_FILE);
lCommand.add("-I=" + IMPOR_TPROTO );
lCommand.add("--java_out=" + JAVA_OUT);
lCommand.add(protos);
Cmd cmd = new Cmd();
cmd.execute(lCommand);
}
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
231
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
调用Java类
调用上面的方法生FirstDemo类后,由于此类过大,这里不列出,只显示如何调用此类:
public class FirstDemoTest {
@Test
public void testMyPerson() throws InvalidProtocolBufferException{
//模拟将对象转成byte[],方便传输
FirstDemo.Demo.Builder builder = Demo.newBuilder();
builder.setId(1);
builder.setName("name");
builder.setEmail("hryou0922@126.com");
Demo person = builder.build();
System.out.println("before :"+ person.toString());
System.out.println("===========Person Byte==========");
for(byte b : person.toByteArray()){
System.out.print(b);
}
System.out.println();
System.out.println(person.toByteString());
System.out.println("================================");
//模拟接收Byte[],反序列化成Person类
byte[] byteArray =person.toByteArray();
MyPerson p2 = MyPerson.parseFrom(byteArray);
System.out.println("after :" +p2.toString());
}
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
281
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
打印内容
before :id: 1
name: "name"
email: "hryou0922@126.com"
===========Person Byte==========
8118411097109101261710411412111111748575050644950544699111109
================================
after :id: 1
name: "name"
email: "hryou0922@126.com"1
2
3
4
5
6
7
8
9
10
111
2
3
4
5
6
7
8
9
10
11
代码
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。