zoukankan      html  css  js  c++  java
  • Netty之ProtoBuf(六)

    Protocol Buffer的基本使用(六)

    一.简介

      Protocol Buffer(简称ProtoBuf)是google的一个语言中立,平台中立,可扩展的对结构化的数据进行序列化的一种机制,和XML类似,但是比XML更小,更快,更简单。你只用一次性的定义你的数据结构,我们可以使用特殊的生成的代码读/写到不同的数据流中或者不同的语言中。这是官网(https://developers.google.com/protocol-buffers/)对Protoco Buffer的描述。如果读者对于Protocol Buffer是什么还有疑问的话,可自行查看其他大神对Protocol Buffer的解释,本博文所采用的是Protocol Buffer的最新版本3.3.0。

    二.Protocol Buffer的使用

    2.1 配置Protocol Buffer的编译器

      A. 下载地址: https://github.com/google/protobuf/releases/tag/v3.3.0, 如下图所示:

      B.解压,如下图所示:  

      C.将解压后的bin目录加入到环境变量,在此笔者不作赘述。

    2.2 编写message文件

      笔者就讲Protocol Buffer官网上的示例demo直接拷贝过来,然后再给出相应的解释,message文件要以 .proto 结尾(至于可不可以不以proto结尾,笔者没有测过,读者可自行测试),文件内容如下: 

    syntax = "proto2";
    
    package tutorial;
    
    option java_package = "com.example.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 phones = 4;
    }
    
    message AddressBook {
      repeated Person people = 1;
    }

    syntax: 语法,即编写该文件所采用的是 protocol buffer 的哪个版本的语法,本示例中采用的是 proto2, 也可以写proto3

    package: 包名,在Java语言中,如果没有指定 java_package,那么在生产Java文件的时候,就以package的值作为Java类的包名;如果指定了java_package,我们依然需要指定package的值,因为在某些非Java语言中是没有包的概念,可以防止命名冲突的问题。

    java_package: Java的包名,可写可不写,不写的情况下,就以package的值作为生成的Java类的包名。

    java_outer_classname: 生产的Java类的类名,如果没有指定的情况下,就以文件名按照驼峰式命名法来定义类名,例如文件名叫做 person_test.proto,在没有指定java_outer_classname的情况下,生成的类名为PersonTest。

    message: 定义消息。消息由一系列的属性组成,每个属性必须有类型,例如int32, int64, bool, float, double, string等。

    enum: 定义枚举类型。

    “=1”,"=2": 用来标记每个属性在二进制编码数据中的唯一标签。属性的标签的值介于1-15比标签为15以上的属性在编码后所占的字节数要少,在优化的时候,我们通常将15以上的标签定义给那些可选的元素。而将1-15作为那些必须的或者可重复的元素的标签。

    元素必须指定修饰符,如下:

      required: 必须的,必须给元素指定一个值。

      optional: 可选的。

      repeated: 可重复的,你可以将其看作一个数组。

    2.3 生成Java文件

      笔者将上述的message文件,命名为 test.proto, 放在电脑的 d:/src/ 目录下。

      打开命令行执行: protoc --proto_path=d:/src/ --java_out=d:/src/ d:/src/test.proto, 如下图所示:

      命令说明:--proto_path 是proto文件的路径,如果不定义,在命令的最后就不能使用绝对路径的方式来指定test.proto,会在执行当前命令所在的目录(如笔者执行protoc命令是在 C:/Users/Administrator 目录下)下去查找 test.proto文件。换句话来说,如果采用绝对路径的方式来指定 test.proto,那么必须使用 --proto_path(简写方式 -I) 指定路径。

    2.4 运行程序

      先导入 protocol buffer 所需要的jar包(https://github.com/google/protobuf/tree/master/java 中有描述),maven依赖如下:

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

      Java代码如下:

    public class Test {
        public static void main(String[] args) throws InvalidProtocolBufferException {
            
            PersonsBook.AddressBook pb = PersonsBook.AddressBook.newBuilder()
                            .addPerson(
                                         PersonsBook.Person.newBuilder().setEmail("345@qq.com").setId(34).setName("zhangsn")
                                      )
                            .addPerson(
                                         PersonsBook.Person.newBuilder().setEmail("123@163.com").setId(12).setName("lisi")
                                      )
                            .build();
        
            byte[] bs = pb.toByteArray();
            
            PersonsBook.AddressBook pb1 = PersonsBook.AddressBook.parseFrom(bs);
            
            List<PersonsBook.Person> list = pb1.getPersonList();
            
            list.forEach(p -> {
                System.out.println(p.getEmail() + ";;" + p.getId() + ";;" + p.getName());
            });
        }
    }  
  • 相关阅读:
    给VS2010自动设置模板,加头注释
    使用委托解决"线程间操作无效: 从不是创建控件“textBox1”的线程访问它" 问题
    正则表达式
    用rz,sz命令在xshell传输文件
    较快的centos源
    《高性能Linux服务器构建实战》一书纠错汇总(2月14日更新)
    cat和rev
    配置centos6.0为Router
    同一个进程中生成的不同线程的栈是互相可见的
    C++用new来创建对象和非new来创建对象的区别
  • 原文地址:https://www.cnblogs.com/miller-zou/p/7000618.html
Copyright © 2011-2022 走看看