Netty系列化之Google Protobuf编解码

黑洞代码 2021-01-14 16:26:27
Google protobuf Netty 系列 系列化


内容目录

Protobuf 简介Protobuf 下载Protobuf 安装编写message.proto文件编译message.proto文件编译后的得到的Message.java测试代码测试结果

Protobuf 简介

  • 轻便高效的结构化数据存储格式
  • 更小、更快、更简洁
  • C++、Java、Python 三种语言的 API

Protobuf 下载

https://github.com/protocolbuffers/protobuf/releases/tag/v3.6.1

Protobuf 安装

tar -xzf protobuf-2.1.0.tar.gz
cd protobuf
./configure
make
make check
make install

编写message.proto文件

syntax = "proto3";
message Person {
int32 id = 1;
string name = 2;
repeated Phone phone = 4;
enum PhoneType {
MOBILE = 0;
HOME = 1;
WORK = 2;
}
message Phone {
string number = 1;
PhoneType type = 2;
}
}

编译message.proto文件

protobuf安装完毕后,根目录会出现protoc文件

protoc --java_out=./data ./data/message.proto
-I 后面是proto文件所在的目录
–java_out 后面是生成java文件存放地址
最后一个参数是proto文件的名称

编译后的得到的Message.java

public final class Message {
private Message() {}
public static void registerAllExtensions(
com.google.protobuf.ExtensionRegistryLite registry) {
}
public static void registerAllExtensions(
com.google.protobuf.ExtensionRegistry registry) {
registerAllExtensions(
(com.google.protobuf.ExtensionRegistryLite) registry);
}
public interface PersonOrBuilder extends
// @@protoc_insertion_point(interface_extends:Person)
com.google.protobuf.MessageOrBuilder {
/**
* <code>int32 id = 1;</code>
*/
int getId();
/**
* <code>string name = 2;</code>
*/
String getName();
/**
* <code>string name = 2;</code>
*/
com.google.protobuf.ByteString
getNameBytes();
/**
* <code>repeated .Person.Phone phone = 4;</code>
*/
java.util.List<Person.Phone>
getPhoneList();
/**
* <code>repeated .Person.Phone phone = 4;</code>
*/
Person.Phone getPhone(int index);
/**
* <code>repeated .Person.Phone phone = 4;</code>
*/
int getPhoneCount();
/**
* <code>repeated .Person.Phone phone = 4;</code>
*/
java.util.List<? extends Person.PhoneOrBuilder>
getPhoneOrBuilderList();
/**
* <code>repeated .Person.Phone phone = 4;</code>
*/
Person.PhoneOrBuilder getPhoneOrBuilder(
int index);
}
/**
* Protobuf type {@code Person}
*/
public static final class Person extends
com.google.protobuf.GeneratedMessageV3 implements
// @@protoc_insertion_point(message_implements:Person)
PersonOrBuilder {
private static final long serialVersionUID = 0L;
// Use Person.newBuilder() to construct.
private Person(com.google.protobuf.GeneratedMessageV3.Builder<?> builder) {
super(builder);
}
private Person() {
id_ = 0;
name_ = "";
phone_ = java.util.Collections.emptyList();
}
@Override
public final com.google.protobuf.UnknownFieldSet
getUnknownFields() {
return this.unknownFields;
}
private Person(
com.google.protobuf.CodedInputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws com.google.protobuf.InvalidProtocolBufferException {
this();
if (extensionRegistry == null) {
throw new NullPointerException();
}
int mutable_bitField0_ = 0;
com.google.protobuf.UnknownFieldSet.Builder unknownFields =
com.google.protobuf.UnknownFieldSet.newBuilder();
try {
boolean done = false;
while (!done) {
int tag = input.readTag();
switch (tag) {
case 0:
done = true;
break;
case 8: {
id_ = input.readInt32();
break;
}
case 18: {
String s = input.readStringRequireUtf8();
name_ = s;
break;
}
case 34: {
if (!((mutable_bitField0_ & 0x00000004) == 0x00000004)) {
phone_ = new java.util.ArrayList<Phone>();
mutable_bitField0_ |= 0x00000004;
}
phone_.add(
input.readMessage(Phone.parser(), extensionRegistry));
break;
}
default: {
if (!parseUnknownFieldProto3(
input, unknownFields, extensionRegistry, tag)) {
done = true;
}
break;
}
}
}
} catch (com.google.protobuf.InvalidProtocolBufferException e) {
throw e.setUnfinishedMessage(this);
} catch (java.io.IOException e) {
throw new com.google.protobuf.InvalidProtocolBufferException(
e).setUnfinishedMessage(this);
} finally {
if (((mutable_bitField0_ & 0x00000004) == 0x00000004)) {
phone_ = java.util.Collections.unmodifiableList(phone_);
}
this.unknownFields = unknownFields.build();
makeExtensionsImmutable();
}
}
public static final com.google.protobuf.Descriptors.Descriptor
getDescriptor() {
return Message.internal_static_Person_descriptor;
}
@Override
protected FieldAccessorTable
internalGetFieldAccessorTable() {
return Message.internal_static_Person_fieldAccessorTable
.ensureFieldAccessorsInitialized(
Person.class, Builder.class);
}
/**
* Protobuf enum {@code Person.PhoneType}
*/
public enum PhoneType
implements com.google.protobuf.ProtocolMessageEnum {
/**
* <code>MOBILE = 0;</code>
*/
MOBILE(0),
/**
* <code>HOME = 1;</code>
*/
HOME(1),
/**
* <code>WORK = 2;</code>
*/
WORK(2),
UNRECOGNIZED(-1),
;
/**
* <code>MOBILE = 0;</code>
*/
public static final int MOBILE_VALUE = 0;
/**
* <code>HOME = 1;</code>
*/
public static final int HOME_VALUE = 1;
/**
* <code>WORK = 2;</code>
*/
public static final int WORK_VALUE = 2;
public final int getNumber() {
if (this == UNRECOGNIZED) {
throw new IllegalArgumentException(
"Can't get the number of an unknown enum value.");
}
return value;
}
/**
* @deprecated Use {@link #forNumber(int)} instead.
*/
@Deprecated
public static PhoneType valueOf(int value) {
return forNumber(value);
}
public static PhoneType forNumber(int value) {
switch (value) {
case 0: return MOBILE;
case 1: return HOME;
case 2: return WORK;
default: return null;
}
}
public static com.google.protobuf.Internal.EnumLiteMap<PhoneType>
internalGetValueMap() {
return internalValueMap;
}
private static final com.google.protobuf.Internal.EnumLiteMap<
PhoneType> internalValueMap =
new com.google.protobuf.Internal.EnumLiteMap<PhoneType>() {
public PhoneType findValueByNumber(int number) {
return PhoneType.forNumber(number);
}
};
public final com.google.protobuf.Descriptors.EnumValueDescriptor
getValueDescriptor() {
return getDescriptor().getValues().get(ordinal());
}
public final com.google.protobuf.Descriptors.EnumDescriptor
getDescriptorForType() {
return getDescriptor();
}
public static final com.google.protobuf.Descriptors.EnumDescriptor
getDescriptor() {
return Person.getDescriptor().getEnumTypes().get(0);
}
private static final PhoneType[] VALUES = values();
public static PhoneType valueOf(
com.google.protobuf.Descriptors.EnumValueDescriptor desc) {
if (desc.getType() != getDescriptor()) {
throw new IllegalArgumentException(
"EnumValueDescriptor is not for this type.");
}
if (desc.getIndex() == -1) {
return UNRECOGNIZED;
}
return VALUES[desc.getIndex()];
}
private final int value;
private PhoneType(int value) {
this.value = value;
}
// @@protoc_insertion_point(enum_scope:Person.PhoneType)
}
public interface PhoneOrBuilder extends
// @@protoc_insertion_point(interface_extends:Person.Phone)
com.google.protobuf.MessageOrBuilder {
/**
* <code>string number = 1;</code>
*/
String getNumber();
/**
* <code>string number = 1;</code>
*/
com.google.protobuf.ByteString
getNumberBytes();
/**
* <code>.Person.PhoneType type = 2;</code>
*/
int getTypeValue();
/**
* <code>.Person.PhoneType type = 2;</code>
*/
PhoneType getType();
}
/**
* Protobuf type {@code Person.Phone}
*/
public static final class Phone extends
com.google.protobuf.GeneratedMessageV3 implements
// @@protoc_insertion_point(message_implements:Person.Phone)
PhoneOrBuilder {
private static final long serialVersionUID = 0L;
// Use Phone.newBuilder() to construct.
private Phone(com.google.protobuf.GeneratedMessageV3.Builder<?> builder) {
super(builder);
}
private Phone() {
number_ = "";
type_ = 0;
}
@Override
public final com.google.protobuf.UnknownFieldSet
getUnknownFields() {
return this.unknownFields;
}
private Phone(
com.google.protobuf.CodedInputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws com.google.protobuf.InvalidProtocolBufferException {
this();
if (extensionRegistry == null) {
throw new NullPointerException();
}
int mutable_bitField0_ = 0;
com.google.protobuf.UnknownFieldSet.Builder unknownFields =
com.google.protobuf.UnknownFieldSet.newBuilder();
try {
boolean done = false;
while (!done) {
int tag = input.readTag();
switch (tag) {
case 0:
done = true;
break;
case 10: {
String s = input.readStringRequireUtf8();
number_ = s;
break;
}
case 16: {
int rawValue = input.readEnum();
type_ = rawValue;
break;
}
default: {
if (!parseUnknownFieldProto3(
input, unknownFields, extensionRegistry, tag)) {
done = true;
}
break;
}
}
}
} catch (com.google.protobuf.InvalidProtocolBufferException e) {
throw e.setUnfinishedMessage(this);
} catch (java.io.IOException e) {
throw new com.google.protobuf.InvalidProtocolBufferException(
e).setUnfinishedMessage(this);
} finally {
this.unknownFields = unknownFields.build();
makeExtensionsImmutable();
}
}
public static final com.google.protobuf.Descriptors.Descriptor
getDescriptor() {
return Message.internal_static_Person_Phone_descriptor;
}
@Override
protected FieldAccessorTable
internalGetFieldAccessorTable() {
return Message.internal_static_Person_Phone_fieldAccessorTable
.ensureFieldAccessorsInitialized(
Phone.class, Builder.class);
}
public static final int NUMBER_FIELD_NUMBER = 1;
private volatile Object number_;
/**
* <code>string number = 1;</code>
*/
public String getNumber() {
Object ref = number_;
if (ref instanceof String) {
return (String) ref;
} else {
com.google.protobuf.ByteString bs =
(com.google.protobuf.ByteString) ref;
String s = bs.toStringUtf8();
number_ = s;
return s;
}
}
/**
* <code>string number = 1;</code>
*/
public com.google.protobuf.ByteString
getNumberBytes() {
Object ref = number_;
if (ref instanceof String) {
com.google.protobuf.ByteString b =
com.google.protobuf.ByteString.copyFromUtf8(
(String) ref);
number_ = b;
return b;
} else {
return (com.google.protobuf.ByteString) ref;
}
}
public static final int TYPE_FIELD_NUMBER = 2;
private int type_;
/**
* <code>.Person.PhoneType type = 2;</code>
*/
public int getTypeValue() {
return type_;
}
/**
* <code>.Person.PhoneType type = 2;</code>
*/
public PhoneType getType() {
@SuppressWarnings("deprecation")
PhoneType result = PhoneType.valueOf(type_);
return result == null ? PhoneType.UNRECOGNIZED : result;
}
private byte memoizedIsInitialized = -1;
@Override
public final boolean isInitialized() {
byte isInitialized = memoizedIsInitialized;
if (isInitialized == 1) return true;
if (isInitialized == 0) return false;
memoizedIsInitialized = 1;
return true;
}
@Override
public void writeTo(com.google.protobuf.CodedOutputStream output)
throws java.io.IOException {
if (!getNumberBytes().isEmpty()) {
com.google.protobuf.GeneratedMessageV3.writeString(output, 1, number_);
}
if (type_ != PhoneType.MOBILE.getNumber()) {
output.writeEnum(2, type_);
}
unknownFields.writeTo(output);
}
@Override
public int getSerializedSize() {
int size = memoizedSize;
if (size != -1) return size;
size = 0;
if (!getNumberBytes().isEmpty()) {
size += com.google.protobuf.GeneratedMessageV3.computeStringSize(1, number_);
}
if (type_ != PhoneType.MOBILE.getNumber()) {
size += com.google.protobuf.CodedOutputStream
.computeEnumSize(2, type_);
}
size += unknownFields.getSerializedSize();
memoizedSize = size;
return size;
}
@Override
public boolean equals(final Object obj) {
if (obj == this) {
return true;
}
if (!(obj instanceof Phone)) {
return super.equals(obj);
}
Phone other = (Phone) obj;
boolean result = true;
result = result && getNumber()
.equals(other.getNumber());
result = result && type_ == other.type_;
result = result && unknownFields.equals(other.unknownFields);
return result;
}
······此处省去N行代码······
// @@protoc_insertion_point(outer_class_scope)
}

测试代码

public class Main {
public static void main(String[] args) {
Message.Person.Builder personBuilder = Message.Person.newBuilder();
personBuilder.setId(12345678);
personBuilder.setName("Admin");
personBuilder.addPhone(Message.Person.Phone.newBuilder().setNumber("10010").setType(Message.Person.PhoneType.MOBILE));
personBuilder.addPhone(Message.Person.Phone.newBuilder().setNumber("10086").setType(Message.Person.PhoneType.HOME));
personBuilder.addPhone(Message.Person.Phone.newBuilder().setNumber("10000").setType(Message.Person.PhoneType.WORK));
Message.Person person = personBuilder.build();
byte[] buff = person.toByteArray();
try {
Message.Person personOut = Message.Person.parseFrom(buff);
System.out.printf("Id:%d, Name:%s\n", personOut.getId(), personOut.getName());
List<Message.Person.Phone> phoneList = personOut.getPhoneList();
for (Message.Person.Phone phone : phoneList) {
System.out.printf("PhoneNumber:%s (%s)\n", phone.getNumber(), phone.getType());
}
} catch (InvalidProtocolBufferException e) {
e.printStackTrace();
}
//Person类的字节码
System.out.println(Arrays.toString(buff));
}
}

测试结果

Id:12345678, Name:Admin
PhoneNumber:10010 (MOBILE)
PhoneNumber:10086 (HOME)
PhoneNumber:10000 (WORK)
[8, -50, -62, -15, 5, 18, 5, 65, 100, 109, 105, 110, 34, 7, 10, 5, 49, 48, 48, 49, 48, 34, 9, 10, 5, 49, 48, 48, 56, 54, 16, 1, 34, 9, 10, 5, 49, 48, 48, 48, 48, 16, 2]

本文分享自微信公众号 - 落叶飞翔的蜗牛(A_GallopingSnail) ,作者:超神的蜗牛

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间: 2018-09-14

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

版权声明
本文为[黑洞代码]所创,转载请带上原文链接,感谢
https://cloud.tencent.com/developer/article/1773781

  1. To what extent can I go out to work?
  2. Java 使用拦截器无限转发/重定向无限循环/重定向次数过多报错(StackOverflowError) 解决方案
  3. Implementation of rocketmq message sending based on JMeter
  4. How to choose the ticket grabbing app in the Spring Festival? We have measured
  5. Implementation of rocketmq message sending based on JMeter
  6. My programmer's Road: self study java
  7. My programmer's Road: self study java
  8. All in one, one article talks about the use of virtual machine VirtualBox and Linux
  9. All in one, one article talks about the use of virtual machine VirtualBox and Linux
  10. Java 使用拦截器无限转发/重定向无限循环/重定向次数过多报错(StackOverflowError) 解决方案
  11. [Java training project] Java ID number recognition system
  12. How does serverless deal with the resource supply demand of k8s in the offline scenario
  13. Detailed explanation of HBase basic principle
  14. Explain the function of thread pool and how to use it in Java
  15. Kubernetes official java client 8: fluent style
  16. 010_MySQL
  17. Vibrant special purchases for the Spring Festival tiktok section, hundreds of good things to make the year more rich flavor.
  18. 010_MySQL
  19. Of the 4 million docker images, 51% have high-risk vulnerabilities
  20. Rocketmq CPP client visual studio 2019 compilation
  21. Rocketmq CPP client visual studio 2019 compilation
  22. Usage of data custom attribute in jquery
  23. Common decompression in Linux
  24. Upload large files in Java
  25. Sentry (v20.12.1) k8s cloud native architecture exploration, sentry for JavaScript manual capture event basic usage
  26. Sentry (v20.12.1) k8s cloud native architecture exploration, sentry for JavaScript manual capture event basic usage
  27. Docker + MySQL Cluster + read / write separation + MYCAT Management + vertical sub database + load balancing
  28. Docker + MySQL Cluster + read / write separation + MYCAT Management + vertical sub database + load balancing
  29. Java use interceptor infinite forwarding / redirection infinite loop / redirection times too many error (stack overflow error) solution
  30. Java use interceptor infinite forwarding / redirection infinite loop / redirection times too many error (stack overflow error) solution
  31. 010_ MySQL
  32. 010_ MySQL
  33. Fast integration of imsdk and Huawei offline push
  34. 消息队列之RabbitMQ
  35. Rabbitmq of message queue
  36. 初学java进制转换方面补充学习
  37. Learn java base conversion supplementary learning
  38. 了解一下RPC,为何诞生RPC,和HTTP有什么不同?
  39. 了解一下RPC,为何诞生RPC,和HTTP有什么不同?
  40. 初学java进制转换方面补充学习
  41. Learn about RPC, why RPC was born, and what's the difference between RPC and HTTP?
  42. Learn about RPC, why RPC was born, and what's the difference between RPC and HTTP?
  43. Learn java base conversion supplementary learning
  44. JDBC测试连接数据库
  45. JDBC test connection database
  46. 大厂面试官竟然这么爱问Kafka,一连八个Kafka问题把我问蒙了?
  47. The interviewers of big factories love to ask Kafka so much. I'm blinded by eight Kafka questions in a row?
  48. 安卓开发和java开发有什么区别!2021年BATJ30套大厂Android经典高频面试题,面试必问
  49. Spring Security OAuth2.0認證授權四:分散式系統認證授權
  50. What's the difference between Android development and java development! 2021 batj30 Android classic high frequency interview questions
  51. Spring security oauth2.0 authentication and authorization 4: distributed system authentication and authorization
  52. Java微服务 vs Go微服务,究竟谁更强!?
  53. 大厂面试官竟然这么爱问Kafka,一连八个Kafka问题把我问蒙了?
  54. Who is stronger, Java microservice vs go microservice!?
  55. Java微服务 vs Go微服务,究竟谁更强!?
  56. The interviewers of big factories love to ask Kafka so much. I'm blinded by eight Kafka questions in a row?
  57. Who is stronger, Java microservice vs go microservice!?
  58. springboot异常处理之404
  59. Spring boot exception handling 404
  60. Spring Boot Security 国际化 多语言 i18n 趟过巨坑