protobuf (java应用实例)

1. 简介:

protobuf是Google开源的一种数据传输协议,类似于XML、JSON等技术,优点是protobuf序列化和反序列化的性能非常好,灵活,高效,自动,跨平台,跨语言,最主要的是它的代码生成机制。只要写一个.proto数据文件,再用编译器编译一下,可以编译成对应语言的代码。本文基于java语言。

安装:
去这里下载对应语言的protobuf,解压。

如果你是Windows环境,则还要下载多一个东西。protobuf-2.5.0-windows.zip。

解压protobuf-2.5.0-windows.zip,把protoc.exe放在Protobuf安装目录下的src里,即可。

2. 简单实例:

1.新建maven项目,引入maven坐标:

<dependency>
     <groupId>com.google.protobuf</groupId>
     <artifactId>protobuf-java</artifactId>
      <version>3.5.1</version>
 </dependency>

2.新建.proto文件 ,addressBook.proto

syntax = "proto2";

option java_package = "inesv.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 phones = 4;
}

message AddressBook {
  repeated Person people = 1;
}

3.编译:
编译有两种方式:

1).直接进入proto的src目录,打cmd命令:

 protoc.exe -I=proto的输入目录 --java_out=java类输出目录 proto的输入目录包括包括proto文件

2).通过java的Runtime编译:编写 GenerareClass.class(这里是处理所有.proto文件)

package inesv.proto;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class GenerareClass {
    public static void main(String[] args) throws IOException {
        String protoPath = System.getProperty("user.dir") + "\\src\\main\\resources\\proto";
        List<String> protoFileList = new ArrayList<String>();
        File f = new File(protoPath);
        File fa[] = f.listFiles();
        for (int i = 0; i < fa.length; i++) {
            File fs = fa[i];
            if (fs.isFile()) {
                protoFileList.add(fs.getName());
            }
        }
        for (String protoFile : protoFileList) {
            System.out.println(protoFile);

            String strCmd = "D:/file/blockChain/protobuf-java-3.5.1/protobuf-3.5.1/src/protoc.exe --java_out=../../java " + protoFile;
            Runtime.getRuntime().exec(strCmd, null, new File(protoPath));
        }
    }
}

到这里,一个proto简单例子就完成了。接下来详细讲解。。

4.对.proto文件详解:

syntax : 指定协议版本
java_package :编译后java文件存放的包
java_outer_classname : 编译生成的java文件名
这个一个地址簿的例子,AddressBook是一个message,而地址簿中又可以嵌套其他message,
message中字段的定义格式为:

修饰符 类型 字段名 = 唯一标识;

修饰符有三种:
required – 表示消息的发送方和接受方都必须处理的字段,此修饰符应该慎用,因为这不利于后期代码的兼容性,比如我们把name字段定义为required,那么接受方必须处理这个属性,如果后期由于业务需要,name字段不要,那么所有接受方都要修改代码,而如果设置为其他修饰符,就不会有这种情况。
optional – 可选
repeated –可多选
类型有:
这里写图片描述

唯一标示:字段名后边的数值为该字段的唯一标示,不能重复.

5.序列化反序列化

package inesv.proto;

import com.google.protobuf.InvalidProtocolBufferException;

import inesv.proto.AddressBookProtos.AddressBook;
import inesv.proto.AddressBookProtos.AddressBook.Builder;
import inesv.proto.AddressBookProtos.Person;
import inesv.proto.AddressBookProtos.Person.PhoneNumber;
import inesv.proto.AddressBookProtos.Person.PhoneType;

public class protoTest {

    public static void main(String[] args) throws InvalidProtocolBufferException {

        Person person = Person.newBuilder()
                               .setId(1)
                               .setName("lin")
                               .setEmail("[email protected]")
                               .addPhones(PhoneNumber.newBuilder().setNumber("15218612888")
                                                                  .setType(PhoneType.WORK))
                               .build();
        AddressBook addressBook = AddressBook.newBuilder()
                                         .addPeople(person)
                                         .build();
        //序列化之前
        System.out.println("序列化之前  "+addressBook.toString());

        //序列化
        byte[] addressBook_se = addressBook.toByteArray();
        System.out.println("序列化  " + addressBook_se);


        //反序列化
        AddressBook AddressBook_de = AddressBook.parseFrom(addressBook_se);
        System.out.println("反序列化 " + AddressBook_de);


    }

}

猜你喜欢

转载自blog.csdn.net/m0_37754981/article/details/78991219