Java中使用Protobuf样例

本文介绍了Google的Protocol Buffers(Protobuf),它是一种轻便的数据序列化协议,用于结构化数据的序列化和反序列化。文中详细讲解了在Windows环境下安装protoc工具,IDEA中安装protobuf插件的步骤,并通过一个Java项目实例展示了如何编写.proto文件,使用protoc编译并运行测试程序,以及序列化和反序列化数据的操作。
摘要由CSDN通过智能技术生成

Protocol Buffers介绍

Protocal Buffers(简称protobuf)是Google开发的一种协议,用于结构化的数据序列化、反序列化,谷歌开发它的目的是提供一种比XML更好的方式来进行系统间通信。

  • 与语言、平台无关,支持Java、C++、Python等多种语言
  • 更简单,更小,更快,更易于维护。很适合做数据存储或RPC数据交换格式
  • 扩展性、兼容性好。更新数据结构,不影响和破坏原有程序

使用ProtoBuf

一、Window安装protoc序列化工具

  • 下载protoc-3.7.1-win64.zip 下载地址

  • 解压安装D:\Soft\protoc-3.7.1-win64

  • 配置到系统环境变量,在Path中添加D:\Soft\protoc-3.7.1-win64\bin
    在这里插入图片描述

  • cmd中测试protoc命令
    在这里插入图片描述

二、Idea安装protobuf插件

  • 下载protobuf-jetbrains-plugin-0.13.0.zip 下载地址
  • idea安装protobuf插件
  • 在这里插入图片描述

三、编写Java项目测试

  • 项目结构
    在这里插入图片描述

  • 创建person.proto文件

syntax = "proto3"; //指定使用proto3语法。没指定编译器默认会使用proto2
option java_package = "org.damon.rpc.protobuf.demo"; //包名
option java_outer_classname = "PersonProtobuf"; //类名

// 定义一个名为person的消息
message Person {

    /*
        字段规则  类型  名称   = 标识号
        repeated Phone phone = 4;

        字段规则:
            repeated -> 字段可出现任意多次(包括0)
        字段类型
            int32、uint32、uint64、sint32、float、double、string等
        字段名称
            xx自定义
        标识号
            1 ~ 2^29-1, or 536,870,911(不可以使用 19000 到 19999 之间的数字,Protobuf协议实现中对这些进行了预留)

    */

    enum PhoneType {
        MOBILE = 0; // 枚举内部的编号第一个必须为0,并且不能重复
        HOME = 1;
        WORK = 2;
    }

    message Phone {
        string number = 1;
        PhoneType type = 2;
    }

    int32 id = 1;
    string name = 2;
    repeated Phone phone = 4;

}

编译成Java文件,进入person.proto文件所在目录,执行编译命令,编译好的文件会自动放在java_package指定目录下

protoc --java_out=../java person.proto
  • Maven引入依赖
<!-- protobuf -->
<dependency>
    <groupId>com.google.protobuf</groupId>
    <artifactId>protobuf-java</artifactId>
    <version>3.7.1</version>
</dependency>
  • 编写测试程序
package org.damon.rpc.protobuf.demo;

import com.google.protobuf.ByteString;

import java.io.IOException;
import java.util.List;

/**
 * @author: wangzisong
 */
public class ProtoBufTest {

    public static void main(String[] args) throws IOException {
        // person构造器
        PersonProtobuf.Person.Builder personBuilder = PersonProtobuf.Person.newBuilder();

        //赋值
        personBuilder.setId(10000);
        personBuilder.setName("张麻子");
        personBuilder.addPhone(PersonProtobuf.Person.Phone.newBuilder().setNumber("13412345678").setType(PersonProtobuf.Person.PhoneType.MOBILE));
        personBuilder.addPhone(PersonProtobuf.Person.Phone.newBuilder().setNumber("0755-1234567").setType(PersonProtobuf.Person.PhoneType.HOME));
        personBuilder.addPhone(PersonProtobuf.Person.Phone.newBuilder().setNumber("0755-6667777-032").setType(PersonProtobuf.Person.PhoneType.WORK));

        System.out.println(personBuilder);
        System.out.println("--------------------------");

        //生成Person对象
        PersonProtobuf.Person person = personBuilder.build();

        // type1:byte[]
        //序列化
        byte[] buff = person.toByteArray();
        System.out.println(buff.toString());
        //反序列化 type1 byte
        PersonProtobuf.Person personOut = PersonProtobuf.Person.parseFrom(buff);
        System.out.println(String.format("Id:%d, 姓名:%s", personOut.getId(), personOut.getName()));

        List<PersonProtobuf.Person.Phone> phoneList = personOut.getPhoneList();
        for (PersonProtobuf.Person.Phone phone : phoneList) {
            System.out.println(String.format("手机号:%s ,类型:%s", phone.getNumber(), phone.getType()));
        }

        // type2:ByteString
        ByteString byteString = person.toByteString();
        System.out.println(byteString.toString());
        // 反序列化
        personOut = PersonProtobuf.Person.parseFrom(byteString);
        System.out.println(String.format("Id:%d, 姓名:%s", personOut.getId(), personOut.getName()));
		
    }

}


  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java 使用 Protobuf (Protocol Buffers) 的过程可以分为以下几个步骤: ### 1. 定义消息结构 首先,你需要在 `.proto` 文件定义你想要序列化的数据结构。例如: ```proto syntax = "proto3"; message Person { string name = 1; int32 id = 2; repeated string phone_numbers = 3; } ``` 在这个例子,我们定义了一个 `Person` 消息,包含了姓名、ID 和一系列电话号码。 ### 2. 生成 Java使用 Protocol Buffers 编译器(protoc)将 `.proto` 文件转换成所需的语言特定文件。对于 Java,运行以下命令: ```bash protoc -I=. --java_out=.$ yourfile.proto ``` 这会生成 `Person.java` 文件,其包含了一组用于处理 `Person` 消息的类。 ### 3. 实现序列化和反序列化 使用生成的 Java 类,你可以轻松地序列化和反序列化 `Person` 对象。例如: #### 序列化 ```java import com.example.yourpackage.Person; // 创建一个Person实例 Person person = Person.newBuilder() .setId(12345) .setName("Alice") .addPhoneNumbers("1234567890") .build(); // 将Person对象序列化为字节数组 byte[] serializedData = person.toByteArray(); ``` #### 反序列化 ```java // 创建一个新的Person.Builder实例,并从字节数组恢复数据 Person newPerson = Person.parseFrom(serializedData); // 获取已反序列化后的Person实例并访问其属性 System.out.println(newPerson.getName()); // 输出 "Alice" ``` ### 相关问题: 1. **如何优化 Protobuf 性能?** - 通过配置减少二进制输出大小,例如避免不必要的字段标记。 - 合理设计 `.proto` 文件,尽量避免嵌套过深,以减少序列化时间和内存消耗。 2. **Protobuf 和 JSON 相比有哪些优势?** - **性能**:Protobuf 的性能通常优于 JSON,因为它是基于二进制而不是文本。 - **紧凑性**:Protobuf 的编码通常比 JSON 更紧凑。 - **速度**:解析和序列化操作更快,因为它们不需要解析整个字符串或数组。 3. **Protobuf 是否支持动态字段?** - Protobuf 默认不支持动态添加未知字段。然而,在某些场景下,如使用反射或第三方库,开发者可能会尝试动态扩展消息。建议预先定义所有需要的消息字段以充分利用性能优势。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值