文档章节

Protocol Buffers(protobuf)在Java开发中使用

boonya
 boonya
发布于 2017/01/13 10:46
字数 1240
阅读 495
收藏 2

关于protobuf的使用我自己有一篇相关的文章:Google Protobuf .proto文件生成Java代码问题处理

文章地址:http://aiilive.blog.51cto.com/1925756/1563449

数据交换的方式很多比如:XML,JSON,Protobuf。虽然protobuf很流行,并且系出名门,可是没怎么用过。通过阅读google developers里关于protocal-buffers的内容基本可以使用它了。如果你访问该链接https://developers.google.com/protocol-buffers/ 失败的话,肯能需要VPN服务。

语言手册:https://developers.google.com/protocol-buffers/docs/proto

Protobuf-Java:https://developers.google.com/protocol-buffers/docs/javatutorial

下载地址:https://developers.google.com/protocol-buffers/docs/downloads

如果是Windows系统建议下载protoc-2.6.0-win32.zip,这样即可省去编译。

官方提供的C++,Python,Java的运行库下载:https://code.google.com/p/protobuf/downloads/list 这里需要注意的是运行库的版本需要和protoc的版本对应。

下文是通过使用protocal-buffers官网提供的一个数据格式的例子来熟悉protocal buffer在Java开发中的基本使用方法。

1.编写一个.proto文件命名为:addressbook.proto,该文件内容来自protocal-buffers官网

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 phone = 4;
}
 
message AddressBook {
  repeated Person person = 1;
}

2.使用protoc-2.6.0-win32.zip解压后的protoc.exe生成Java类

查询protoc.exe帮助:

D:\__dev\jar\protobuff>protoc.exe -h

生成Java类:

D:\__dev\jar\protobuff>protoc.exe --proto_path=F:\__eclipse\test\proto 
--java_out=F:\__eclipse\test\src F:\__eclipse\test\proto\addressbook.proto

说明: 项目结构

上图中addressbook.proto数据格式文件,AddressBookProtos.java是生成的java类,protobuf-java-2.5.0.jar是Java运行时类库。

3.使用AddressBookProtos类来实现对象的序列号和反序列化,了解Protocol-buffers jar的相关API

代码示例:

package com.example.test;
 
import java.util.Arrays;
 
import com.example.tutorial.AddressBookProtos.AddressBook;
import com.example.tutorial.AddressBookProtos.Person;
import com.google.protobuf.InvalidProtocolBufferException;
 
public class AddressBookProtoUse {
 
    public static void main(String[] args) {
        //构建一个Person对象
        Person person = Person
                .newBuilder()
                .setEmail("zhangsan@163.com")
                .setId(10086)
                .setName("zhangsan")
                .addPhone(
                        Person.PhoneNumber.newBuilder().setNumber("186")
                                .setType(Person.PhoneType.HOME).build())
                .build();
        System.out.println("打印输出Person对象信息:");
        System.out.println(person);
        System.out.println("Person对象调用toString()方法:");
        System.out.println(person.toString());
 
        System.out.println("Person对象字段是否初始化:" + person.isInitialized());
 
        // 序列号
        System.out.println("Person对象调用toByteString()方法:");
        System.out.println(person.toByteString());
 
        System.out.println("Person对象调用toByteArray()方法:");
        System.out.println(Arrays.toString(person.toByteArray()));
         
        try {
            System.out.println("反序列化后的对象信息:");
            // 反序列化
            Person newPerson = Person.parseFrom(person.toByteArray());
            System.out.println(newPerson);
            newPerson = Person.parseFrom(person.toByteString());
            System.out.println(newPerson);
        } catch (InvalidProtocolBufferException e) {
            e.printStackTrace();
        }
 
        // 向地址簿添加两条Person信息
        AddressBook.Builder books = AddressBook.newBuilder();
        books.addPerson(person);
        books.addPerson(Person.newBuilder(person).setEmail("tom@163.com")
                .build());
        System.out.println("AddressBook对象信息:");
        System.out.println(books.build());
 
    }
}

运行结果:

打印输出Person对象信息:
name: "zhangsan"
id: 10086
email: "zhangsan@163.com"
phone {
  number: "186"
  type: HOME
}
 
Person对象调用toString()方法:
name: "zhangsan"
id: 10086
email: "zhangsan@163.com"
phone {
  number: "186"
  type: HOME
}
 
Person对象字段是否初始化:true
Person对象调用toByteString()方法:
<ByteString@89ec59 size=40>
Person对象调用toByteArray()方法:
[10, 8, 122, 104, 97, 110, 103, 115, 97, 110, 16, -26, 78, 26, 16, 122, 104, 97, 110, 103, 115, 97, 110, 64, 49, 54, 51, 46, 99, 111, 109, 34, 7, 10, 3, 49, 56, 54, 16, 1]
反序列化后的对象信息:
name: "zhangsan"
id: 10086
email: "zhangsan@163.com"
phone {
  number: "186"
  type: HOME
}
 
name: "zhangsan"
id: 10086
email: "zhangsan@163.com"
phone {
  number: "186"
  type: HOME
}
 
AddressBook对象信息:
person {
  name: "zhangsan"
  id: 10086
  email: "zhangsan@163.com"
  phone {
    number: "186"
    type: HOME
  }
}
person {
  name: "zhangsan"
  id: 10086
  email: "tom@163.com"
  phone {
    number: "186"
    type: HOME
  }
}

探究AddressBookProtos类: 类

**a.**构造Person对象,Person类继承自com.google.protobuf.GeneratedMessage类,而GeneratedMessage类继承自AbstractMessage类,并且实现了序列化接口Serializable。在AbstractMessage类中重写了toString()方法,具体内容如下:

@Override
  public final String toString() {
    return TextFormat.printToString(this);
  }

于是有了Person对象调用toString()方法后直接输出Person对象的文本内容。

** b.**toByteString()返回的ByteString是一个不可变的byte序列,由AbstractMessage类实现。toByteArray()返回byte[]。这两个方法都是对象进行序列化的方法。

** c.**isInitialized()判断对象的字段是否初始化,该方法与Person类的initFields()方法相关。

initFields()源代码:

private void initFields() {
      name_ = "";
      id_ = 0;
      email_ = "";
      phone_ = java.util.Collections.emptyList();
    }

**d.**Person类提供了一系列的反序列化的重载方法用来讲数据反序列化为Person对象。 输入图片说明 **e.**关于Person对象的Build

Person类中有一个Builder的内部类,该类用来构建Person对象,并且为Person对象添加数据。

public static final class Builder extends
        com.google.protobuf.GeneratedMessage.Builder<Builder>
       implements com.example.tutorial.AddressBookProtos.PersonOrBuilder

4.通过学习官网的实例,手绘一张Java使用protobuf的基本流程图 输入图片说明

本文转载自:http://aiilive.blog.51cto.com/1925756/1563449

boonya
粉丝 76
博文 307
码字总数 61606
作品 0
海淀
高级程序员
私信 提问
Protobuf Thrift数据描述语言调研

编者注 由于json是字符进行传送,尤其是传送float参数,会直接导致数据传输量暴增。则需要使用二进制化的跨语言传输方法。编者找到Google Protocol Buffers,Apache Thrift,Apache avro。 ...

抢小孩糖吃
2018/01/20
107
0
protocol buffers入门基础知识(一)

protocol buffers简介 下载地址 2.protocol buffers优势 3.Protocol Buffers 3.0 技术手册 4.一个pb的demo 执行编译命令生成文件...

Cobbage
2018/10/01
48
0
在netty中使用google protobuf

netty版本5.0,google protobuf版本2.5. netty自带的例子io.netty.example.worldclock,就是使用protobuf作为网络协议. 本文实现客户端-服务端之间请求-响应的网络协议,会在worldclock例子上稍...

走走_
2014/03/05
5.9K
0
用 Maven 实现一个 protobuf 的 Java 例子

原文出处:jihite 1. 介绍Protocol Buffers Protocal Buffers(简称protobuf)是谷歌的一项技术,用于结构化的数据序列化、反序列化,常用于RPC 系统(Remote Procedure Call Protocol System...

jihite
2018/05/14
0
0
protocol buffer 对socket协议封装成二进制传输

protocol buffer 是 google 的一种数据交换的格式,它独立于语言,独立于平台。google 提供了三种语言的实现:java、c++ 和 python,每一种实现都包含了相应语言的编译器以及库文件。由于它是...

MrLovelyCbb
2012/02/15
765
0

没有更多内容

加载失败,请刷新页面

加载更多

在Ignite中自定义身份认证安全插件

Ignite集群搭建完成之后,应用就可以接入集群进行各种操作了,但是默认的集群,没有安全保护机制,任何应用、支持JDBC的客户端,只要知道集群节点的IP地址,都可以接入集群,这造成了一定的安...

李玉珏
35分钟前
21
0
浅谈proxy代理模式

一、前言 代理是代替服务器去接受请求者的请求的中间人。我们也听说过代理服务器,它的作用的帮助客户端去请求客户端想要的资源,为什么要通过代理呢,那是因为客户端直接访问服务器会被拒绝...

青衣霓裳
36分钟前
5
0
Java多线程之原子操作类

在并发编程中很容易出现并发安全问题,最简单的例子就是多线程更新变量i=1,多个线程执行i++操作,就有可能获取不到正确的值,而这个问题,最常用的方法是通过Synchronized进行控制来达到线程...

全菜工程师小辉
47分钟前
7
0
arcgis arcpy 克里金插值 掩膜 配置符号系统 自动生成图片

整体思路,最后要加载到mxd文件中,然后导出图片 首先加载mxd文件 mxd = mapping.MapDocument(r"./11.mxd") 然后读取数据 并加载到图层中 sr = arcpy.SpatialReference(4326) # 读取csv...

可达鸭Go
今天
4
0
漂亮有创意的思维导图模板分享

相信很多人使用在绘制思维导图时很喜欢使用模板进行编辑,它能够让你在短时间内快速创造出一个风格明显好看的思维导图,对绘制时间以及使用够感受影响都是较为深刻的,下面为大家分享几款漂亮...

干货趣分享
今天
4
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部