使用 protoc
生成 Java 包文件
protoc
简介
protoc
是 Protocol Buffers 编译器,用于将 .proto
文件转换为目标语言的代码。在您的项目中,protoc
主要用于定义和规范消息体格式,确保消息在不同系统之间的一致性。protoc
是 Protocol Buffers(简称 Protobuf)的核心工具,通过它可以生成包含消息定义的类,方便在代码中使用。 用 protoc
的主要目的是规范消息体格式。在分布式系统或跨平台应用中,消息格式的一致性至关重要。通过使用 protoc
,我们可以确保不同组件之间传递的消息遵循相同的结构和规则,减少错误并提高系统的可靠性。
Windows 使用 protoc 生成 Java 文件
在 Windows 系统上,您可以按照以下步骤使用 protoc
从 .proto
文件生成代码:
1. 下载 Protocol Buffers 编译器 (protoc
):
- 首先,访问 GitHub 上的 Protocol Buffers 官方发布页面。
- 下载最新版本的
protoc-<version>-win64.zip
文件。 - 将下载的 ZIP 文件解压缩到您指定的目录,例如
C:\protoc
。
2. 生成代码:
- 打开命令提示符(cmd),然后导航到包含
.proto
文件的目录,或者直接指定.proto
文件的完整路径。 - 使用
protoc
命令生成代码。
Java 代码生成示例命令:
D:\dev_program\protoc-28.0-rc-2-win64\bin\protoc --java_out=E:\code\java\project-litongjava\netty-im-server\src\main\java ChatPacket.proto
proto 文件和生成的文件
ChatPacket.proto
syntax = "proto3";
package com.litongjava.im.netty.protobuf;
option java_outer_classname = "ChatPacketOuter";
// 定义一个消息
message ChatPacket {
int32 code=1;
string msg=2;
}
`ChatPacketOuter.java
生成的文件是 ChatPacketOuter.java
,文件长度超过 600 行。
// Generated by the protocol buffer compiler. DO NOT EDIT!
// NO CHECKED-IN PROTOBUF GENCODE
// source: ChatPacket.proto
// Protobuf Java Version: 4.28.0-rc2
package com.litongjava.im.netty.protobuf;
public final class ChatPacketOuter {
private ChatPacketOuter() {
}
static {
com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion(com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, /* major= */ 4, /* minor= */ 28, /* patch= */ 0, /* suffix= */ "-rc2",
ChatPacketOuter.class.getName());
}
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 ChatPacketOrBuilder extends
// @@protoc_insertion_point(interface_extends:com.litongjava.im.netty.protobuf.ChatPacket)
com.google.protobuf.MessageOrBuilder {
/**
* <code>int32 code = 1;</code>
*
* @return The code.
*/
int getCode();
/**
* <code>string msg = 2;</code>
*
* @return The msg.
*/
java.lang.String getMsg();
/**
* <code>string msg = 2;</code>
*
* @return The bytes for msg.
*/
com.google.protobuf.ByteString getMsgBytes();
}
/**
* <pre>
* 定义一个消息
* </pre>
*
* Protobuf type {@code com.litongjava.im.netty.protobuf.ChatPacket}
*/
public static final class ChatPacket extends com.google.protobuf.GeneratedMessage implements
// @@protoc_insertion_point(message_implements:com.litongjava.im.netty.protobuf.ChatPacket)
ChatPacketOrBuilder {
private static final long serialVersionUID = 0L;
static {
com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion(com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, /* major= */ 4, /* minor= */ 28, /* patch= */ 0, /* suffix= */ "-rc2",
ChatPacket.class.getName());
}
// Use ChatPacket.newBuilder() to construct.
private ChatPacket(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
super(builder);
}
private ChatPacket() {
msg_ = "";
}
public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() {
return com.litongjava.im.netty.protobuf.ChatPacketOuter.internal_static_com_litongjava_im_netty_protobuf_ChatPacket_descriptor;
}
@java.lang.Override
protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() {
return com.litongjava.im.netty.protobuf.ChatPacketOuter.internal_static_com_litongjava_im_netty_protobuf_ChatPacket_fieldAccessorTable
.ensureFieldAccessorsInitialized(com.litongjava.im.netty.protobuf.ChatPacketOuter.ChatPacket.class, com.litongjava.im.netty.protobuf.ChatPacketOuter.ChatPacket.Builder.class);
}
public static final int CODE_FIELD_NUMBER = 1;
private int code_ = 0;
/**
* <code>int32 code = 1;</code>
*
* @return The code.
*/
@java.lang.Override
public int getCode() {
return code_;
}
public static final int MSG_FIELD_NUMBER = 2;
@SuppressWarnings("serial")
private volatile java.lang.Object msg_ = "";
/**
* <code>string msg = 2;</code>
*
* @return The msg.
*/
@java.lang.Override
public java.lang.String getMsg() {
java.lang.Object ref = msg_;
if (ref instanceof java.lang.String) {
return (java.lang.String) ref;
} else {
com.google.protobuf.ByteString bs = (com.google.protobuf.ByteString) ref;
java.lang.String s = bs.toStringUtf8();
msg_ = s;
return s;
}
}
/**
* <code>string msg = 2;</code>
*
* @return The bytes for msg.
*/
@java.lang.Override
public com.google.protobuf.ByteString getMsgBytes() {
java.lang.Object ref = msg_;
if (ref instanceof java.lang.String) {
com.google.protobuf.ByteString b = com.google.protobuf.ByteString.copyFromUtf8((java.lang.String) ref);
msg_ = b;
return b;
} else {
return (com.google.protobuf.ByteString) ref;
}
}
private byte memoizedIsInitialized = -1;
@java.lang.Override
public final boolean isInitialized() {
byte isInitialized = memoizedIsInitialized;
if (isInitialized == 1)
return true;
if (isInitialized == 0)
return false;
memoizedIsInitialized = 1;
return true;
}
@java.lang.Override
public void writeTo(com.google.protobuf.CodedOutputStream output) throws java.io.IOException {
if (code_ != 0) {
output.writeInt32(1, code_);
}
if (!com.google.protobuf.GeneratedMessage.isStringEmpty(msg_)) {
com.google.protobuf.GeneratedMessage.writeString(output, 2, msg_);
}
getUnknownFields().writeTo(output);
}
@java.lang.Override
public int getSerializedSize() {
int size = memoizedSize;
if (size != -1)
return size;
size = 0;
if (code_ != 0) {
size += com.google.protobuf.CodedOutputStream.computeInt32Size(1, code_);
}
if (!com.google.protobuf.GeneratedMessage.isStringEmpty(msg_)) {
size += com.google.protobuf.GeneratedMessage.computeStringSize(2, msg_);
}
size += getUnknownFields().getSerializedSize();
memoizedSize = size;
return size;
}
@java.lang.Override
public boolean equals(final java.lang.Object obj) {
if (obj == this) {
return true;
}
if (!(obj instanceof com.litongjava.im.netty.protobuf.ChatPacketOuter.ChatPacket)) {
return super.equals(obj);
}
com.litongjava.im.netty.protobuf.ChatPacketOuter.ChatPacket other = (com.litongjava.im.netty.protobuf.ChatPacketOuter.ChatPacket) obj;
if (getCode() != other.getCode())
return false;
if (!getMsg().equals(other.getMsg()))
return false;
if (!getUnknownFields().equals(other.getUnknownFields()))
return false;
return true;
}
@java.lang.Override
public int hashCode() {
if (memoizedHashCode != 0) {
return memoizedHashCode;
}
int hash = 41;
hash = (19 * hash) + getDescriptor().hashCode();
hash = (37 * hash) + CODE_FIELD_NUMBER;
hash = (53 * hash) + getCode();
hash = (37 * hash) + MSG_FIELD_NUMBER;
hash = (53 * hash) + getMsg().hashCode();
hash = (29 * hash) + getUnknownFields().hashCode();
memoizedHashCode = hash;
return hash;
}
public static com.litongjava.im.netty.protobuf.ChatPacketOuter.ChatPacket parseFrom(java.nio.ByteBuffer data) throws com.google.protobuf.InvalidProtocolBufferException {
return PARSER.parseFrom(data);
}
public static com.litongjava.im.netty.protobuf.ChatPacketOuter.ChatPacket parseFrom(java.nio.ByteBuffer data, com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws com.google.protobuf.InvalidProtocolBufferException {
return PARSER.parseFrom(data, extensionRegistry);
}
public static com.litongjava.im.netty.protobuf.ChatPacketOuter.ChatPacket parseFrom(com.google.protobuf.ByteString data) throws com.google.protobuf.InvalidProtocolBufferException {
return PARSER.parseFrom(data);
}
public static com.litongjava.im.netty.protobuf.ChatPacketOuter.ChatPacket parseFrom(com.google.protobuf.ByteString data, com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws com.google.protobuf.InvalidProtocolBufferException {
return PARSER.parseFrom(data, extensionRegistry);
}
public static com.litongjava.im.netty.protobuf.ChatPacketOuter.ChatPacket parseFrom(byte[] data) throws com.google.protobuf.InvalidProtocolBufferException {
return PARSER.parseFrom(data);
}
public static com.litongjava.im.netty.protobuf.ChatPacketOuter.ChatPacket parseFrom(byte[] data, com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws com.google.protobuf.InvalidProtocolBufferException {
return PARSER.parseFrom(data, extensionRegistry);
}
public static com.litongjava.im.netty.protobuf.ChatPacketOuter.ChatPacket parseFrom(java.io.InputStream input) throws java.io.IOException {
return com.google.protobuf.GeneratedMessage.parseWithIOException(PARSER, input);
}
public static com.litongjava.im.netty.protobuf.ChatPacketOuter.ChatPacket parseFrom(java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws java.io.IOException {
return com.google.protobuf.GeneratedMessage.parseWithIOException(PARSER, input, extensionRegistry);
}
public static com.litongjava.im.netty.protobuf.ChatPacketOuter.ChatPacket parseDelimitedFrom(java.io.InputStream input) throws java.io.IOException {
return com.google.protobuf.GeneratedMessage.parseDelimitedWithIOException(PARSER, input);
}
public static com.litongjava.im.netty.protobuf.ChatPacketOuter.ChatPacket parseDelimitedFrom(java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws java.io.IOException {
return com.google.protobuf.GeneratedMessage.parseDelimitedWithIOException(PARSER, input, extensionRegistry);
}
public static com.litongjava.im.netty.protobuf.ChatPacketOuter.ChatPacket parseFrom(com.google.protobuf.CodedInputStream input) throws java.io.IOException {
return com.google.protobuf.GeneratedMessage.parseWithIOException(PARSER, input);
}
public static com.litongjava.im.netty.protobuf.ChatPacketOuter.ChatPacket parseFrom(com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws java.io.IOException {
return com.google.protobuf.GeneratedMessage.parseWithIOException(PARSER, input, extensionRegistry);
}
@java.lang.Override
public Builder newBuilderForType() {
return newBuilder();
}
public static Builder newBuilder() {
return DEFAULT_INSTANCE.toBuilder();
}
public static Builder newBuilder(com.litongjava.im.netty.protobuf.ChatPacketOuter.ChatPacket prototype) {
return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
}
@java.lang.Override
public Builder toBuilder() {
return this == DEFAULT_INSTANCE ? new Builder() : new Builder().mergeFrom(this);
}
@java.lang.Override
protected Builder newBuilderForType(com.google.protobuf.GeneratedMessage.BuilderParent parent) {
Builder builder = new Builder(parent);
return builder;
}
/**
* <pre>
* 定义一个消息
* </pre>
*
* Protobuf type {@code com.litongjava.im.netty.protobuf.ChatPacket}
*/
public static final class Builder extends com.google.protobuf.GeneratedMessage.Builder<Builder> implements
// @@protoc_insertion_point(builder_implements:com.litongjava.im.netty.protobuf.ChatPacket)
com.litongjava.im.netty.protobuf.ChatPacketOuter.ChatPacketOrBuilder {
public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() {
return com.litongjava.im.netty.protobuf.ChatPacketOuter.internal_static_com_litongjava_im_netty_protobuf_ChatPacket_descriptor;
}
@java.lang.Override
protected com.google.protobuf.GeneratedMessage.FieldAccessorTable internalGetFieldAccessorTable() {
return com.litongjava.im.netty.protobuf.ChatPacketOuter.internal_static_com_litongjava_im_netty_protobuf_ChatPacket_fieldAccessorTable
.ensureFieldAccessorsInitialized(com.litongjava.im.netty.protobuf.ChatPacketOuter.ChatPacket.class, com.litongjava.im.netty.protobuf.ChatPacketOuter.ChatPacket.Builder.class);
}
// Construct using
// com.litongjava.im.netty.protobuf.ChatPacketOuter.ChatPacket.newBuilder()
private Builder() {
}
private Builder(com.google.protobuf.GeneratedMessage.BuilderParent parent) {
super(parent);
}
@java.lang.Override
public Builder clear() {
super.clear();
bitField0_ = 0;
code_ = 0;
msg_ = "";
return this;
}
@java.lang.Override
public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() {
return com.litongjava.im.netty.protobuf.ChatPacketOuter.internal_static_com_litongjava_im_netty_protobuf_ChatPacket_descriptor;
}
@java.lang.Override
public com.litongjava.im.netty.protobuf.ChatPacketOuter.ChatPacket getDefaultInstanceForType() {
return com.litongjava.im.netty.protobuf.ChatPacketOuter.ChatPacket.getDefaultInstance();
}
@java.lang.Override
public com.litongjava.im.netty.protobuf.ChatPacketOuter.ChatPacket build() {
com.litongjava.im.netty.protobuf.ChatPacketOuter.ChatPacket result = buildPartial();
if (!result.isInitialized()) {
throw newUninitializedMessageException(result);
}
return result;
}
@java.lang.Override
public com.litongjava.im.netty.protobuf.ChatPacketOuter.ChatPacket buildPartial() {
com.litongjava.im.netty.protobuf.ChatPacketOuter.ChatPacket result = new com.litongjava.im.netty.protobuf.ChatPacketOuter.ChatPacket(this);
if (bitField0_ != 0) {
buildPartial0(result);
}
onBuilt();
return result;
}
private void buildPartial0(com.litongjava.im.netty.protobuf.ChatPacketOuter.ChatPacket result) {
int from_bitField0_ = bitField0_;
if (((from_bitField0_ & 0x00000001) != 0)) {
result.code_ = code_;
}
if (((from_bitField0_ & 0x00000002) != 0)) {
result.msg_ = msg_;
}
}
@java.lang.Override
public Builder mergeFrom(com.google.protobuf.Message other) {
if (other instanceof com.litongjava.im.netty.protobuf.ChatPacketOuter.ChatPacket) {
return mergeFrom((com.litongjava.im.netty.protobuf.ChatPacketOuter.ChatPacket) other);
} else {
super.mergeFrom(other);
return this;
}
}
public Builder mergeFrom(com.litongjava.im.netty.protobuf.ChatPacketOuter.ChatPacket other) {
if (other == com.litongjava.im.netty.protobuf.ChatPacketOuter.ChatPacket.getDefaultInstance())
return this;
if (other.getCode() != 0) {
setCode(other.getCode());
}
if (!other.getMsg().isEmpty()) {
msg_ = other.msg_;
bitField0_ |= 0x00000002;
onChanged();
}
this.mergeUnknownFields(other.getUnknownFields());
onChanged();
return this;
}
@java.lang.Override
public final boolean isInitialized() {
return true;
}
@java.lang.Override
public Builder mergeFrom(com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException {
if (extensionRegistry == null) {
throw new java.lang.NullPointerException();
}
try {
boolean done = false;
while (!done) {
int tag = input.readTag();
switch (tag) {
case 0:
done = true;
break;
case 8: {
code_ = input.readInt32();
bitField0_ |= 0x00000001;
break;
} // case 8
case 18: {
msg_ = input.readStringRequireUtf8();
bitField0_ |= 0x00000002;
break;
} // case 18
default: {
if (!super.parseUnknownField(input, extensionRegistry, tag)) {
done = true; // was an endgroup tag
}
break;
} // default:
} // switch (tag)
} // while (!done)
} catch (com.google.protobuf.InvalidProtocolBufferException e) {
throw e.unwrapIOException();
} finally {
onChanged();
} // finally
return this;
}
private int bitField0_;
private int code_;
/**
* <code>int32 code = 1;</code>
*
* @return The code.
*/
@java.lang.Override
public int getCode() {
return code_;
}
/**
* <code>int32 code = 1;</code>
*
* @param value The code to set.
* @return This builder for chaining.
*/
public Builder setCode(int value) {
code_ = value;
bitField0_ |= 0x00000001;
onChanged();
return this;
}
/**
* <code>int32 code = 1;</code>
*
* @return This builder for chaining.
*/
public Builder clearCode() {
bitField0_ = (bitField0_ & ~0x00000001);
code_ = 0;
onChanged();
return this;
}
private java.lang.Object msg_ = "";
/**
* <code>string msg = 2;</code>
*
* @return The msg.
*/
public java.lang.String getMsg() {
java.lang.Object ref = msg_;
if (!(ref instanceof java.lang.String)) {
com.google.protobuf.ByteString bs = (com.google.protobuf.ByteString) ref;
java.lang.String s = bs.toStringUtf8();
msg_ = s;
return s;
} else {
return (java.lang.String) ref;
}
}
/**
* <code>string msg = 2;</code>
*
* @return The bytes for msg.
*/
public com.google.protobuf.ByteString getMsgBytes() {
java.lang.Object ref = msg_;
if (ref instanceof String) {
com.google.protobuf.ByteString b = com.google.protobuf.ByteString.copyFromUtf8((java.lang.String) ref);
msg_ = b;
return b;
} else {
return (com.google.protobuf.ByteString) ref;
}
}
/**
* <code>string msg = 2;</code>
*
* @param value The msg to set.
* @return This builder for chaining.
*/
public Builder setMsg(java.lang.String value) {
if (value == null) {
throw new NullPointerException();
}
msg_ = value;
bitField0_ |= 0x00000002;
onChanged();
return this;
}
/**
* <code>string msg = 2;</code>
*
* @return This builder for chaining.
*/
public Builder clearMsg() {
msg_ = getDefaultInstance().getMsg();
bitField0_ = (bitField0_ & ~0x00000002);
onChanged();
return this;
}
/**
* <code>string msg = 2;</code>
*
* @param value The bytes for msg to set.
* @return This builder for chaining.
*/
public Builder setMsgBytes(com.google.protobuf.ByteString value) {
if (value == null) {
throw new NullPointerException();
}
checkByteStringIsUtf8(value);
msg_ = value;
bitField0_ |= 0x00000002;
onChanged();
return this;
}
// @@protoc_insertion_point(builder_scope:com.litongjava.im.netty.protobuf.ChatPacket)
}
// @@protoc_insertion_point(class_scope:com.litongjava.im.netty.protobuf.ChatPacket)
private static final com.litongjava.im.netty.protobuf.ChatPacketOuter.ChatPacket DEFAULT_INSTANCE;
static {
DEFAULT_INSTANCE = new com.litongjava.im.netty.protobuf.ChatPacketOuter.ChatPacket();
}
public static com.litongjava.im.netty.protobuf.ChatPacketOuter.ChatPacket getDefaultInstance() {
return DEFAULT_INSTANCE;
}
private static final com.google.protobuf.Parser<ChatPacket> PARSER = new com.google.protobuf.AbstractParser<ChatPacket>() {
@java.lang.Override
public ChatPacket parsePartialFrom(com.google.protobuf.CodedInputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws com.google.protobuf.InvalidProtocolBufferException {
Builder builder = newBuilder();
try {
builder.mergeFrom(input, extensionRegistry);
} catch (com.google.protobuf.InvalidProtocolBufferException e) {
throw e.setUnfinishedMessage(builder.buildPartial());
} catch (com.google.protobuf.UninitializedMessageException e) {
throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial());
} catch (java.io.IOException e) {
throw new com.google.protobuf.InvalidProtocolBufferException(e).setUnfinishedMessage(builder.buildPartial());
}
return builder.buildPartial();
}
};
public static com.google.protobuf.Parser<ChatPacket> parser() {
return PARSER;
}
@java.lang.Override
public com.google.protobuf.Parser<ChatPacket> getParserForType() {
return PARSER;
}
@java.lang.Override
public com.litongjava.im.netty.protobuf.ChatPacketOuter.ChatPacket getDefaultInstanceForType() {
return DEFAULT_INSTANCE;
}
}
private static final com.google.protobuf.Descriptors.Descriptor internal_static_com_litongjava_im_netty_protobuf_ChatPacket_descriptor;
private static final com.google.protobuf.GeneratedMessage.FieldAccessorTable internal_static_com_litongjava_im_netty_protobuf_ChatPacket_fieldAccessorTable;
public static com.google.protobuf.Descriptors.FileDescriptor getDescriptor() {
return descriptor;
}
private static com.google.protobuf.Descriptors.FileDescriptor descriptor;
static {
java.lang.String[] descriptorData = { "\n\020ChatPacket.proto\022 com.litongjava.im.ne" + "tty.protobuf\"\'\n\nChatPacket\022\014\n\004code\030\001 \001(\005"
+ "\022\013\n\003msg\030\002 \001(\tB\021B\017ChatPacketOuterb\006proto3" };
descriptor = com.google.protobuf.Descriptors.FileDescriptor.internalBuildGeneratedFileFrom(descriptorData, new com.google.protobuf.Descriptors.FileDescriptor[] {});
internal_static_com_litongjava_im_netty_protobuf_ChatPacket_descriptor = getDescriptor().getMessageTypes().get(0);
internal_static_com_litongjava_im_netty_protobuf_ChatPacket_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable(
internal_static_com_litongjava_im_netty_protobuf_ChatPacket_descriptor, new java.lang.String[] { "Code", "Msg", });
descriptor.resolveAllFeaturesImmutable();
}
// @@protoc_insertion_point(outer_class_scope)
}
使用 protobuf
为了正确使用 Protobuf 并提高传输效率,您需要在客户端和服务器端都使用 Protobuf 进行数据的序列化和反序列化。以下是如何在 Java 中对 ChatPacket
进行序列化和反序列化的示例。
首先,确保您已经生成了 Protobuf 的 Java 类。根据您的 .proto
文件,应该已经生成了 ChatPacketOuter.java
,其中包含了 ChatPacket
类。
序列化示例(客户端发送数据):
import com.litongjava.im.netty.protobuf.ChatPacketOuter.ChatPacket;
public class ProtobufSerializationExample {
public static void main(String[] args) {
// 构建 ChatPacket 对象
ChatPacket packet = ChatPacket.newBuilder().setCode(101).setMsg("{\"userId\":1}").build();
// 序列化为字节数组
byte[] data = packet.toByteArray();
// 16
System.out.println(data.length);
}
}
反序列化示例(服务器接收数据):
import com.litongjava.im.netty.protobuf.ChatPacketOuter.ChatPacket;
import com.google.protobuf.InvalidProtocolBufferException;
public class ProtobufDeserializationExample {
public static void main(String[] args) {
byte[] data = receiveData();
try {
// 使用 Protobuf 反序列化
ChatPacket packet = ChatPacket.parseFrom(data);
// 访问 packet 中的字段
int code = packet.getCode();
String msg = packet.getMsg();
System.out.println("Code: " + code);
System.out.println("Message: " + msg);
} catch (InvalidProtocolBufferException e) {
System.err.println("解析 Protobuf 数据失败: " + e.getMessage());
}
}
private static byte[] receiveData() {
ChatPacket packet = ChatPacket.newBuilder().setCode(101).setMsg("{\"userId\":1}").build();
byte[] data = packet.toByteArray();
return data;
}
}
注意事项
将 JSON 字符串转换为二进制数据并发送,然后在服务器端使用 Protobuf 的 parseFrom
方法解析,并不会提高效率,也不会减少数据大小。Protobuf 的 parseFrom
方法期望的是使用 Protobuf 自身的序列化机制生成的二进制数据,而不是像 JSON 字符串转换成的任意二进制数据。Protobuf 的效率提升来源于客户端和服务器都使用 Protobuf 进行序列化和反序列化,完全绕过 JSON。
Protobuf 的优点
Protobuf 是一种序列化结构化数据的方法。它使用二进制格式,具有以下特点:
- 紧凑性:相比 JSON 或 XML,数据大小更小。
- 高效性:编码和解码速度更快。
- 语言中立:可在多种编程语言中使用。