protobuf入门学习

     来学习一下protobuf。它是google出的序列化产品。性能/效率高。可以用它进行模块之间的通信。json和protobuf之间,protobuf对于数据量较大的时候传输性能明显较好。

      首先要下载protoc.exe,他可以让proto文件生成java文件。proto文件中定义了一个类中的属性,类型,包名。需要用protoc.exe去生成。下文会有详细介绍。这里请下载protoc2.6.1exe。与protobuf-java-2.6.1.jar包的版本相同。这个jar包需要在maven中添加dependency。

	<dependency>
			<groupId>com.google.protobuf</groupId>
			<artifactId>protobuf-java</artifactId>
			<version>2.6.1</version>
		</dependency>
protoc.exe的下载我是直接在csdn上下载的资源。也可以从https://github.com/google/protobuf下载,但是因为exe直接下载的地址无法访问,需要下载源码用vs编译生成。会比较麻烦。

       还有一个jar包,定义了序列化和反序列化的实现函数,并没有深入去看。

下面来讲解下具体的例子。

         首先要写一个.proto文件。用来定义要序列类的基本信息。src/main/java文件夹下新建msg.proto

syntax="proto2";  
package tutorial;  
  
option java_package = "com.baidu.protobuf";  <span style="color:#ff0000;">生成的包名</span>
option java_outer_classname = "AddressBookProtos";   <span style="color:#ff0000;">生成的类名</span>
  
message Person {   <span style="color:#ff6666;"> 一个类</span>
  required string name = 1;    <span style="color:#ff0000;">required表示要序列化的类中必须带有这个属性</span>
  required int32 id = 2;       <span style="color:#ff0000;">数字是序列化后二进制中唯一对应的属性,类中的各个属性对应的不同</span>
  optional string email = 3;   <span style="color:#ff0000;">optional和required不同,是可带可不带的意思</span>
  
  enum PhoneType {   <span style="color:#ff0000;">枚举类</span>
    MOBILE = 0;  
    HOME = 1;  
    WORK = 2;  
  }  
  
  message PhoneNumber {  
    required string number = 1;  
    optional PhoneType type = 2 [default = HOME];  <span style="color:#ff0000;">不带的话,默认值是HOME</span>
  }  
  
  repeated PhoneNumber phone = 4;    <span style="color:#ff0000;">repeated代表数组,list类型</span>
}  
  
message AddressBook {  
  repeated Person person = 1;  
}  

下面把protoc.exe也复制到这个文件夹下。用cmd进入这个文件夹。输入protoc --java_out=. msg.proto。

这个命令的用法 :protoc –java_out=源码输出路径   proto文件路径

现在发现这个文件夹下多了com.baidu.protobuf包。也有了一个类。


编写一个类进行测试

package com.baidu.test;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

import com.baidu.protobuf.AddressBookProtos.AddressBook;
import com.baidu.protobuf.AddressBookProtos.Person;

public class Test {
	public static void print(AddressBook addressBook) {
		for(Person person : addressBook.getPersonList()) {
			System.out.println("Person ID: " + person.getId());
			System.out.println(" Name: " + person.getName());
			if(person.hasEmail()) {
				System.out.println(" E-mail address: " + person.getEmail());
			}
			
			for(Person.PhoneNumber phoneNumber : person.getPhoneList()) {
				switch(phoneNumber.getType()) {
				case MOBILE:
					System.out.print(" Moblie phone #: ");
					break;
				case HOME:
					System.out.print(" Home phone #: ");
					break;
				case WORK :
					System.out.print(" Work phone #: ");
					break;
				}
				System.out.println(phoneNumber.getNumber());
			}
		}
	}
	
	public void serialize() throws IOException {
		Person john = 
				Person.newBuilder()
				.setId(1234)
				.setName("John Doe")
				.setEmail("abc@qq.com")
				.addPhone(
						Person.PhoneNumber.newBuilder()
						.setNumber("555-4321")
						.setType(Person.PhoneType.HOME))
						.build();     // 要序列化的对象,格式就是类.newBuilder().set属性.build()
		
		AddressBook.Builder addressBook = AddressBook.newBuilder();
		addressBook.addPerson(john);
		
		//serialize to disk 
		FileOutputStream output = new FileOutputStream("addressbook.pbd");
		addressBook.build().writeTo(output); // this function do serialization
		output.close();
	}
	
	public void deserialize() throws FileNotFoundException, IOException {
		AddressBook addressBook =
				AddressBook.parseFrom(new FileInputStream("addressbook.pbd"));
		// 这个parseFrom函数可以直接反序列化
		print(addressBook);
	}
	
	public static void main(String[] args) throws IOException {
		Test demo = new Test();
		demo.serialize();
		System.out.println("serialize to disk success!!");  
        System.out.println("start deserialize......");  
        demo.deserialize();
		
	}
}
运行后就可以看到结果。整个项目结构为:




小结

优点:

1.  性能好/效率高。对比xml冗余信息少,解析速度更快,时间和空间开销小。

2.  代码生成简单,定义好message数据结构,使用protobuf内置编译器就能得到“包装类”代码,使用包装类用来读取message数据结构。

3.  同时支持“向前兼容”和“向后兼容”。

向前兼容:服务端方升级数据结构后,客户端能正常识别新版本数据。

向后兼容:客户端升级数据结构后,依然可以正常收取服务端的老版本数据。只需要客户端将新的属性设置为“非必填(optional)”即可。

这样可以灵活地对数据结构进行升级,而无需大规模重构代码。

4.  支持多种编程语言(官方支持C++、Java、Python;开源社区响应支持了ActionScript、C#、Lisp、Erlang、Perl、PHP、Ruby等)。使用 Google 提供的 Compiler 包,也可以开发出支持其他语言的新的编译器。

缺点:

1)  应用不够广。相比XML而言,在知名度、应用广度等方面都不如。

2)  二进制格式导致可读性差。protobuf文件传输存储是二进制格式。

3)  缺乏自描述。一般来说,XML是自描述的,而protobuf格式则不是,除非有.proto文件,否则很难看懂代码。


再贴一个protobuf与netty配合使用的博文地址。可以看下。

http://blog.youkuaiyun.com/xuechongyang/article/details/8659739



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值