Protobuf与Java互转使用

近期实现的一个功能中,由于后台需要的请求入参数据量过大,而req的载体有大小限制,所以采用了先使用pb文件存储数据上云,云文件索引作为req入参的方案。
本文记录其中使用pb与Java互转的过程。

前言

protobuf是谷歌推出的序列化协议,有比json所占字节少体积小、序列化传输快的特点。再加上其同样有平台无关的特性,protobuf得以广泛应用。

常见的使用场景:

  1. 前端与后端的通信数据载体

  2. 多端复用的数据结构,如草稿库

  3. 作为轻量级文件存储数据(本次的使用场景)

ProtoBuf转成Java过程记录

编写proto文件

|

1
syntax = "proto2";    package demo;    option java_multiple_files = true;  option java_package = "com.darrenyuen.demo.protos";  option java_outer_classname = "DemoProtos";    message Person {  optional string name = 1;  optional int32 id = 2;  optional string email = 3;    enum PhoneType {  	MOBILE = 0;  	HOME = 1;  	WORK = 2;  }    message PhoneNumber {  optional string number = 1;  optional PhoneType type = 2 [default = HOME];  }    repeated PhoneNumber phones = 4;  }    message AddressBook {  	repeated Person people = 1;  }

|

命令编译

proto语法是跨平台的,所以我们需要需要对应平台的编译器工具,编译成java文件,比如笔者在MacOs下,需要下载这个平台的编译工具。

|

1
protoc --java_out=输出目录 编译文件 -I=编译文件所在的文件夹# 编译.proto文件为Kotlin文件# protoc --proto_path=src/test/proto --kotlin_out=src/test/kotlin src/test/proto/addressbook.proto

|

  • protoc:Protobuf 编译器的命令行工具,用于编译 Protobuf 文件。

  • --java_out=输出目录:指定生成的 Java 代码的输出目录。编译器会将生成的代码放置在这个目录下。

  • 编译文件:Protobuf 文件的路径,这些文件包含了消息定义。

  • -I=编译文件所在的文件夹:指定 Protobuf 文件所在的目录。编译器会在这个目录下搜索指定的文件。
    执行编译后,便可拷贝生成java文件到工程中使用

集成插件编译

  1. 集成gradle插件
    |
1
// 根目录 build.gradle文件,引入插件buildscript {repositories {  	mavenCentral()  }    dependencies {  	classpath 'com.google.protobuf:protobuf-gradle-plugin:0.8.18'  	}  }

|
``
|

1
// app目录 build.gradle 引入pb-java库implementation 'com.google.protobuf:protobuf-java:3.8.0'

|

|

1
// app目录 build.gradle 声明使用插件plugins {   	id 'com.google.protobuf'  }

|

  1. 编译配置
    |
1
// app目录 build.gradlesourceSets {  	main {   		proto {  			srcDir 'src/main/proto'  		}  	}  }protobuf {  	protoc {  		artifact = 'com.google.protobuf:protoc:3.18.1'  	}  	generateProtoTasks {  		all().each { task ->  			task.builtins {  				java {  					option "lite"  				}  				// Generates Python code  				// python { }  				// Generates Kotlin code 				// kotlin { }			}  		}  	}  }

|

  1. 使用结果文件
    编译后,结果文件会生成并存储在{PROJECT_ROOT}/app/build/generated/source/proto中,可拷贝到工程中使用

Java数据序列化成pb文件

|

1
val filePath = "dir/${System.currentTimeMillis()}.pb"  var outputStream: FileOutputStream? = nulltry {  	val demoParam = addressBookBuilder.build()  	FileUtils.createOrExistsFile(File(filePath))  	outputStream = FileOutputStream(filePath)  try {  	demoParam.writeTo(outputStream)  } catch (t: Throwable) {    }  } catch (t: Throwable) {   } finally {  	outputStream?.close()  }

|

参考文章:
如何在Android上从零使用Protobuf
适用于 Gradle 的 Protobuf 插件