Live2D

protoBuf的学习

2.mac环境安装

brew命令安装下载

brew install protobuf

查看安装目录

which protoc

配置环境变量

sudo vi ~/.bash_profile
export PROTOC=/usr/local/bin/protoc
source ~/.bash_profile

查看版本

protoc --version

3.在java中简单使用

使用Protoc生成java类

首先在项目中创建一个demo.proto文件,选择txt文件就行了

//使用 proto3 语法 ,未指定则使用proto2
syntax = "proto3";

//生成 proto 文件所在包路径
package com.wl.protobuf;

//生成 proto 文件所在包路径
option java_package = "com.wl.protobuf";

//生成 proto 文件名
option java_outer_classname="DemoProto";

message Demo{
  //自身属性
  int32 id = 1;
  string code = 2;
  string name = 3;
}

然后打开项目所在的控制台输入以下指令

protoc --java_out=src/main/java  src/main/resources/demo.proto
  • --java_out=src/main/java 就是生成的java文件的路径
  • src/main/resources/demo.proto 是 proto文件的路径
  • protoc是protobuf的指令

可以看到生成了一个DemoProto.java文件,这个类可以帮我们生成序列化的对象和反序列化

在idea中安装插件 Protobuf GeneratorProtocol Buffer Editor 可以让idea识别到 .proto文件

image

下载完成后找到 tools

image

修改规则

image

然后可以快速生成DemoProto.java文件

image

序列化和反序列化

在得到 Protoc生成的java类以后,可以使用这个DemoProto.java类进行序列化和反序列化

加入maven依赖

 <!--  protobuf 支持 Java 核心包 这里最好对应自己系统上的版本-->
 <dependency>
     <groupId>com.google.protobuf</groupId>
     <artifactId>protobuf-java</artifactId>
     <version>3.19.4</version>
 </dependency>
 <!--  proto 与 Json 互转会用到-->
 <dependency>
     <groupId>com.google.protobuf</groupId>
     <artifactId>protobuf-java-util</artifactId>
     <version>3.15.3</version>
 </dependency>

序列化和反序列化测试代码

package com.wl.protobuf;

import com.google.protobuf.InvalidProtocolBufferException;
import com.google.protobuf.util.JsonFormat;

import java.util.Arrays;

/**
 * @author 没有梦想的java菜鸟
 * @Date 创建时间:2022/5/17 下午6:06
 * @qq 2315290571
 * @Description protobuf 在java 的序列化和反序列化
 */
public class ProtoBufTest {
    public static void main(String[] args) throws Exception {
        // 初始化数据
        DemoProto.Demo.Builder builder = DemoProto.Demo.newBuilder();
        builder.setId(1)
                .setCode("1001")
                .setName("小明")
                .build();
        // 序列化
        DemoProto.Demo build = builder.build();
        // 转换成字节数组
        byte[] contentBytes = build.toByteArray();
        System.out.println("序列化后的数组内容:"+Arrays.toString(contentBytes));
        System.out.println("序列化后的数组长度:"+contentBytes.length);
        // 反序列化
        DemoProto.Demo content = DemoProto.Demo.parseFrom(contentBytes);
        // 转json
        String jsonContent = JsonFormat.printer().print(content);
        System.out.println("内容是:");
        System.out.println(jsonContent);

    }
}

运行结果如下:

image

4. java和protobuf数据类型的对应

字段规则

共有三种字段规则:

  • required:字段是必须且唯一的

  • optional:字段可以出现0次或多次,可选字段

  • repeate:字段可以任意次数出现,一般用于生成java的List集合

required

required  int32 id = 1 [default = 123]

optional

optional string name = 1 [default = "张三"]

repeate

//list String
repeated string strList = 5;
//list 对象
repeated Role roleList = 6;
字段编号

在消息定义中,每个字段都有唯一的一个标识符。[1,15]之内的标识号在编码的时候会占用一个字节。[16,2047]之内的标识号则占用2个字节。

字段类型

基本数据类型image

复杂数据类型

创建一个名为test.protoTeacher.proto的文件,然后使用 protoc生成Java文件

test.proto
//使用 proto3 语法 ,未指定则使用proto2
syntax = "proto3";
//生成 proto 文件所在包路径
package com.wl.protobuf;
//生成 proto 文件所在包路径
option java_package = "com.wl.protobuf";
// 生成的文件名
option java_outer_classname = "ComplexProto";
// 引入外部文件
import "Teacher.proto";

// 创建一个User类
message User{
  // 定义string,int类型的map集合
  map<string, int32> intMap = 3;
  // 定义string,Student类型的map集合
  map<string, Student> stuMap = 2;
  // 定义string 类型的list集合
  repeated string list = 8;
  // 引入外部的Teacher.proto的文件
  repeated Teacher teacherList = 4;
}
// 定义Student对象
message Student{
  string stuId = 1;
  string stuName = 5;
  string stuSchool = 6;
}
Teacher.proto
//使用 proto3 语法 ,未指定则使用proto2
syntax = "proto3";
//生成 proto 文件所在包路径
package com.wl.protobuf;
//生成 proto 文件所在包路径
option java_package = "com.wl.protobuf";
// 生成的文件名
option java_outer_classname = "TeacherProto";
message Teacher{
  string tId=1;
  string tName=2;
  string tSchool=3;
}
Test测试类
package com.wl.protobuf.complex;

import com.google.protobuf.InvalidProtocolBufferException;
import com.google.protobuf.util.JsonFormat;

/**
 * @author 没有梦想的java菜鸟
 * @Date 创建时间:2022/5/18 下午12:18
 * @qq 2315290571
 * @Description 测试类
 */
public class Test {
    public static void main(String[] args) throws InvalidProtocolBufferException {
        // 赋值Student 对象
        ComplexeProto.Student.Builder stuBuilder = ComplexeProto.Student.newBuilder();

        ComplexeProto.Student student = stuBuilder.setStuId("1001")
                .setStuName("小明")
                .setStuSchool("北京大学")
                .build();
        ComplexeProto.Student student2 = stuBuilder.setStuId("1002")
                .setStuName("小李")
                .setStuSchool("上海大学")
                .build();
        // 赋值Teacher对象
        TeacherProto.Teacher.Builder tBuilder = TeacherProto.Teacher.newBuilder();

        TeacherProto.Teacher.Builder t1 = tBuilder.setTId("2001")
                .setTName("胡老师")
                .setTSchool("北京大学");

        TeacherProto.Teacher.Builder t2 = tBuilder.setTId("2002")
                .setTName("李老师")
                .setTSchool("上海大学");
        // 给User对象赋值
        ComplexeProto.User.Builder userBuilder = ComplexeProto.User.newBuilder();
        // 给intMap赋值
        userBuilder.putIntMap("java", 1);
        userBuilder.putIntMap("kotlin", 2);
        // 给stuMap赋值
        userBuilder.putStuMap("北京", student);
        userBuilder.putStuMap("上海", student2);
        // 给 String类型的list集合赋值
        userBuilder.addList("A");
        userBuilder.addList("B");
        userBuilder.addList("C");
        userBuilder.addList("D");
        // 给teacherList赋值
        userBuilder.addTeacherList(t1);
        userBuilder.addTeacherList(t2);

        // 序列化
        ComplexeProto.User serialize = userBuilder.build();
        // 转换成字节数组
        byte[] bytes = serialize.toByteArray();
        // 反序列化
        ComplexeProto.User content = ComplexeProto.User.parseFrom(bytes);
        // 转json
        String json = JsonFormat.printer().print(content);
        System.out.println(json);

    }
}

输出结果

image

posted @ 2022-05-18 16:36  没有梦想的java菜鸟  阅读(200)  评论(4编辑  收藏  举报