Protobuf在java项目中的使用

Protobuf在java项目中的使用

protobuf的介绍和安装这里就不多说了,不太清楚的可以参考我的上一篇博文()。这里我们就基于java的项目,引入并使用protobuf来处理数据。

资源以及环境介绍:

         1JDK  1.7.0_67

         2Eclipse  jee-indigo

         3protobuf:  proto.exe 和protobuf-2.5.0.jar

         其中jdk和eclipse为下面demo的一个开发环境,这里版本号为该开发环境的一个版本,供参考。而protobuf使用的2.5版本,博文后面将提供protobuf相关资源的个人云盘下载地址,有需要的可自行下载。

 具体步骤:

一、创建项目,添加protobuf支持

         在eclipse中创建一个web项目(不限定是web项目,其他java项目均可,这里创建web项目只为后续中导入jar包方便),然后将protobuf基于java类库protobuf-2.5.0.jar导入项目中,即将protobuf-2.5.0.jar文件复制到lib文件夹下就行。

二、编写.proto文件,确定消息体

         在项目项目的src下创建一个包用于存放.proto文件,再在该包下创建一个普通文件,以.proto为扩展名。这里包名和.proto文件名可以根据需要自行命名。打开.proto文件,根据需要编写消息体,这里贴出笔者demo的.proto文件代码

package demo;

option java_package = "sample.demo";
option java_outer_classname = "ProtoDemo";

message Student {
  required int32 id = 1;
  required string name = 2;
  optional string email = 3;

  enum Sex {
    MAN = 0;
    WOMAN = 1;
  }
  optional Sex sex = 4 [default = MAN];
  
  enum PhoneType{
   	MOBILE = 0;
    HOME = 1;
    WORK = 2;
  }
  
  message PhoneNumber {
    required string number = 1;
    optional PhoneType type = 2 [default = HOME];
  }

  repeated PhoneNumber phone = 5;
}

补充:就该消息体的定义的做简单说明

         1.  option java_package指定该proto文件生成的java类的包名

    2.  optionjava_outer_classname指定proto文件生成的java类的类名

         3.  message是消息定义的关键字,对应着java中的class,在该proto文件的生成的java类文件中,将会定义了一个内部类Student以及Student类的内部类PhoneNumber

         4.  required 、optional、repeated均为限制附,修饰消息体中的字段,说明如下:

           required:该字段为必要字段,既在序列化和反序列化之前该字段必须已经被赋值, 每个消息中可以包含0个或多个optional类型的字段

           optional:该字段为非必要字段

           repeated:表示的字段可以包含0个或多个数据,实际在生成的java类中,被repeated修饰的字段将被声明成一个List<字段类型>类型

         5.int32和string 定义字段类型,类似于java中的int和String,关于类型的对照表如下:

.proto Type

C++ Type

Java Type

Notes

double

double

double

 

float

float

float

 

int32

int32

int

使用可变长编码方式。编码负数时不够高效——如果你的字段可能含有负数,那么请使用sint32。

int64

int64

long

使用可变长编码方式。编码负数时不够高效——如果你的字段可能含有负数,那么请使用sint64。

uint32

uint32

int

Uses variable-length encoding.

uint64

uint64

long

Uses variable-length encoding.

sint32

int32

int

使用可变长编码方式。有符号的整型值。编码时比通常的int32高效。

sint64

int64

long

使用可变长编码方式。有符号的整型值。编码时比通常的int64高效。

fixed32

uint32

int

总是4个字节。如果数值总是比总是比228大的话,这个类型会比uint32高效。

fixed64

uint64

long

总是8个字节。如果数值总是比总是比256大的话,这个类型会比uint64高效。.

sfixed32

int32

int

总是4个字节。

sfixed64

int64

long

总是8个字节。

bool

bool

boolean

 

string

string

String

一个字符串必须是UTF-8编码或者7-bit ASCII编码的文本。

bytes

string

ByteString

可能包含任意顺序的字节数据。

6 其中id =1 和 name = 2 ,id和name均消息体中的字段名,在生产的java类中将成为消息类Student的属性的属性名,而标签数字1和2则表示不同的字段在序列化后的二进制数据中的布局位置,需要注意的是该值在同一message中不能重复。

7其中enum Sex {},定义一个名为Sex的枚举类型,在后面可以用Sex来声明消息体中字段的属性

以上说明均基于java,由于官方网址一直访问不进去,关于proto定义的详细说明参考了博文:http://www.cnblogs.com/stephen-liu74/archive/2013/01/02/2841485.html

   http://ju.outofmemory.cn/entry/109294

三、编译.proto文件,生产对应的java类文件

         1打开cmd窗口,将cmd工作空间定位到.proto文件的所在位置,即执行命令:

                            cd  C:\server

         这里笔者是先将.proto文件复制到了server目录下进行编译的

         2再在该目录下执行命令:

                            protoc--java_out=. protodemo.proto

         这里protodemo.proto为你编写的.proto文件的文件名,protoc--java_out表示以java的形式编译该.proto文件,将会在目录下得到一个sample\demo\ProtoDemo.java文件

         3将生成的文件及目录整个复制到项目的src下(这里就将sample文件夹复制到src下),将会在src下看到一个包为sample.demo,在包下有一个ProtoDemo的类

 

以上方式为手动编译,而Eclipse是可以添加protobuf插件的,可以实现自动编译。笔者想在eclipse上在线安装protobuf插件来着,但是一直访问不进去插件地址,可能是网速不行,读者可以试试,安装后配置protobuf的编译器就可以实现自动编译.proto文件。笔者由于eclipse没有安装上插件这里就不再详细介绍了,读者可以参考博文:

         http://www.360doc.com/content/14/0718/15/16044571_395291178.shtml

四、将java实例转换成字节数据,再将字节数据转换成java实例

         现在在我们的java项目就有了生成的ProtoDemo类,现在编写代码来使用该来转换相关信息数据。创建了一个Test类,具体代码如下

package proto.demo.test;

import java.util.List;
import com.google.protobuf.InvalidProtocolBufferException;
import sample.demo.ProtoDemo;
import sample.demo.ProtoDemo.Student;
import sample.demo.ProtoDemo.Student.PhoneNumber;

public class Test {
	
	/**
	 * protobuf是一种数据交换的格式,以二进制的格式进行数据交换,主要用于网络传输、配置文件、数据存储等诸多领域
	 * 
	 * 下面我们就将指定格式的信息转换成字节形式数据,然后将字节形式数据恢复成指定格式的信息
	 * 读者可以简单的看下.proto文件生成的ProtoDemo类的结构
	 */
	public static void main(String[] args) {
	
		//获得Student对象
		//这里的Student对象构造器被私有化,我们通过通过Student的内部类Builder来构建builder
		ProtoDemo.Student.Builder builder =  ProtoDemo.Student.newBuilder();
		//Student类未提供相关属性的set方法,而Student的内部类builder提供了构建Student相关属性的set方法
		builder.setId(1);
		builder.setName("凌晨1点21分");
		builder.setEmail("2474600377@qq.com");
		builder.setSex(ProtoDemo.Student.Sex.MAN);
		//相同方法获取PhoneNumber对象
		ProtoDemo.Student.PhoneNumber.Builder phb = ProtoDemo.Student.PhoneNumber.newBuilder();
		phb.setNumber("123456789");
		phb.setType(ProtoDemo.Student.PhoneType.HOME);
		PhoneNumber pn = phb.build();
		builder.addPhone(pn);
		//这里再获取了一个PhoneNumber对象,原理一样
		PhoneNumber pn2 = ProtoDemo.Student.PhoneNumber.newBuilder()
				.setNumber("789456123").setType(ProtoDemo.Student.PhoneType.MOBILE).build();
		builder.addPhone(pn2);
		
		Student stu = builder.build();
		//这里你我们将封装有数据的对象实例,转换为字节数组,用于数据传输、存储等
		byte[] stuByte = stu.toByteArray();
		
		//这里得到了stuBte字节数组后,我们可以将该数据进行数据传输或存储,这里至于用什么技术传输就根据具体情况而定
		//假如这里stuByt通过传输,下面的代码接到了该数据
		
		//接收方 ,这里为了方便我们就写在一个类里面
		try {
			//将字节数据转换为对应的对象实例
			Student stu2 = ProtoDemo.Student.parseFrom(stuByte);
			//这里得到了Student实例了,就可以根据需要来操作里面的数据了
			System.out.println("学生ID:"+stu2.getId());
			System.out.println("姓名:"+stu2.getName());
			System.out.println("性别:"+(stu2.getSex().getNumber()==0?"男":"女"));
			System.out.println("邮箱:"+stu2.getEmail());
			//这里phoneNumber字段
			List<PhoneNumber> phList = stu2.getPhoneList();
			for (PhoneNumber p : phList) {
				System.out.println(p.getType().toString()+"电话:"+p.getNumber());
			}
			
		} catch (InvalidProtocolBufferException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

程序运行结果截图如下:

相关资源:

  一、本文参考资源

         1Protobuf 语法指南:

                   http://ju.outofmemory.cn/entry/109294

                   http://www.cnblogs.com/stephen-liu74/archive/2013/01/02/2841485.html

         2.Eclipse中添加Protobuf支持

             http://www.360doc.com/content/14/0718/15/16044571_395291178.shtml

  二、本文demo相关资源(个人云盘)

         1.protobuf相关资源下载:

                   http://pan.baidu.com/s/1c0I4cU0

         2.本文demo资源:

                  http://pan.baidu.com/s/1i330Kgl


protobufProtocol Buffers)是一种高效的序列化数据格式,由Google开发。它可以将结构化的数据转换成二进制文件,便于网络传输和存储,并支持跨语言的数据交换。在Java项目使用protobuf,你需要按照以下步骤操作: 1. **添加依赖**: - 首先,在你的Maven项目中,需要添加Google Protobuf的库作为依赖。在`pom.xml`中加入以下内容: ```xml <dependencies> <dependency> <groupId>com.google.protobuf</groupId> <artifactId>protobuf-java</artifactId> <version>3.X.Y</version> <!-- 更新到最新的稳定版本 --> </dependency> </dependencies> ``` 确保替换`X.Y`为你找到的最新版本号。 2. **生成Java代码**: 使用protoc编译器(protoc)将`.proto`协议缓冲文件转换为Java源代码。运行命令: ``` protoc -I=path/to/your/proto/files --java_out=target/classes path/to/your/proto/file.proto ``` 这里`path/to/your/proto/files`是你存放`.proto`文件的目录,`target/classes`是生成Java文件的目标路径。 3. **包含生成的Java包**: 在你的Java代码中,记得导入生成的Java包,以便使用protobuf消息类。 4. **使用消息类**: 创建或解析protobuf消息实例,就像处理普通的Java类一样。例如,你可以创建一个新的实例: ```java MyMessage message = MyMessage.newBuilder() .setField1(value) .build(); ``` 5. **序列化与反序列化**: 对于数据的序列化,可以使用`toByteArray()`方法;反序列化则通过`parseFrom(byte[] bytes)`或`parseDelimitedFrom(InputStream input)`等方法。
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值