Protobuf在java中的简单使用实例

2023-11-08

TTprotobuf是一种跨语言的数据转换协议,由google开源的,已支持大部份语言。在一般的数据交互过程中都是使用json,xml等来做数据的转换,这其中涉及复杂的解析与序列化反序列化问题,如果在大量数据并发请求时,也会导致性能问题。protobuf采用Varint编码技术,在某种程度上减少数字的字节数,关于Varint的实现原理可以参考:

https://segmentfault.com/a/1190000020500985?utm_source=tag-newest

由于protobuf是跨语言的,所以用不同的语言序列化对象后,生成一段字节码,之后可以其他任何语言反序列化并自用,大大方便了跨语言的通讯,同时也提高了效率。

本文主要是Protobuf针对java在后台开发的应用,用一个简单的实例工程来实践。

 在开始项目之前,先安装protobuf插件,方便后面编写proto文件

  • 新建一个maven工程,在项目main下新建目录,命名为proto
  • 并导入以下pom依赖(本项目使用protobuf版本为3.5.1):
<dependencies>
    <dependency>
        <groupId>com.google.protobuf</groupId>
        <artifactId>protobuf-java</artifactId>
        <version>3.5.1</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/com.google.protobuf/protobuf-java-util -->
    <dependency>
        <groupId>com.google.protobuf</groupId>
        <artifactId>protobuf-java-util</artifactId>
        <version>3.5.1</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/io.grpc/grpc-all -->
    <dependency>
        <groupId>io.grpc</groupId>
        <artifactId>grpc-all</artifactId>
        <version>1.11.0</version>
    </dependency>
</dependencies>
<build>
    <extensions>
        <extension>
            <groupId>kr.motd.maven</groupId>
            <artifactId>os-maven-plugin</artifactId>
            <version>1.5.0.Final</version>
        </extension>
    </extensions>
    <plugins>
        <plugin>
            <groupId>org.xolstice.maven.plugins</groupId>
            <artifactId>protobuf-maven-plugin</artifactId>
            <version>0.5.0</version>
            <configuration>
                <protocArtifact>
                    com.google.protobuf:protoc:3.1.0:exe:${os.detected.classifier}
                </protocArtifact>
                <pluginId>grpc-java</pluginId>
                <pluginArtifact>
                    io.grpc:protoc-gen-grpc-java:1.11.0:exe:${os.detected.classifier}
                </pluginArtifact>
            </configuration>
            <executions>
                <execution>
                    <goals>
                        <goal>compile</goal>
                        <goal>compile-custom</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>
  • 需要先自行配置好maven
  • 新建一个包:com.study.myprotobuf.dto:
  • 新建两个proto文件:student.proto,course.proto

  •  编写proto文件之前,可以先大概百度了解一下proto的语法,实际也跟java或c的类似,有一个头部定义包,文件名,引入其他proto文件等。在这里说明一下,proto文件实际不是业务端要用到的,而是一个模板文件,google开源支持的语言都可以使用这个proto文件。
  • 以下是两个proto文件的内容,课程模板与学生模板文件:
// 指定模板类的包路径
option java_package = "com.study.myprotobuf.dto";
// 指定模板类的名称,名称必须是有实际业务意义的
option java_outer_classname = "CourseProto";

// 定义课程
message course{
  // 课程名称
  required string name = 1;
  // 课程分数
  required int32 score = 2;
}
// 指定模板类的包路径
option java_package = "com.study.myprotobuf.dto";
// 指定模板类的名称,名称必须是有实际业务意义的
option java_outer_classname = "StudentProto";
// 引入课程模板
import "course.proto";

// 定义学生模板
message student{
  // 学生名称
  required string name = 1;
  // 学生年龄
  required int32 age = 2;
  // 学生所修课程,可能是多门,是一组数组
  repeated course course = 3;
}
  • 如果maven配置成功,可以打开maven的Plugins下的protobuf节点中的compile,双击进行编译:

  • 编译成功后,生成target目录,找到对应的proto类,如下所示: 
  • 以上生成java代码类方式也可以通过命令的方式:

    从github下载protoc工具:

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

    添加环境变量:

     打开cmd命令窗口,输入protoc --version,查看版本号:

    在本地磁盘新建存放proto文件和生成java类的文件目录:

    D:/protofile(proto文件)

    D:/protojava(生成的java类)

    在cmd命令窗口输入以下命令:

    protoc -I=D:/protojava --java_out=D:/protojava D:/protofile/teacher.proto --proto_path=D:/protofile

    执行成功后可以D:/protofile目录中生成protobuf的java类文件。

  •  将这两个java类复制到之前新建的dto包中,此时,可以看到google生成的对象proto的源代码,里面实际包含了模板类的创建,序列化,反序列化和json转换等方法
  • 新建一个test包,新增一个类TestMyProtobuf进行测试,完成的代码如下:
package com.study.myprotobuf.test;

import com.google.protobuf.InvalidProtocolBufferException;
import com.google.protobuf.util.JsonFormat;
import com.study.myprotobuf.dto.CourseProto;
import com.study.myprotobuf.dto.StudentProto;

import java.util.Arrays;

public class TestMyProtobuf {
    public static void main(String[] args) {
        // 生成课程1对象
        CourseProto.course.Builder courseBuilder1 = CourseProto.course.newBuilder();
        courseBuilder1.setName("Java");
        courseBuilder1.setScore(99);
        CourseProto.course course1 = courseBuilder1.build();

        // 生成课程2对象
        CourseProto.course.Builder courseBuilder2 = CourseProto.course.newBuilder();
        courseBuilder2.setName("Python");
        courseBuilder2.setScore(98);
        CourseProto.course course2 = courseBuilder2.build();

        // 生成学生对象
        StudentProto.student.Builder studentBuilder = StudentProto.student.newBuilder();
        studentBuilder.setName("Lucy");
        studentBuilder.setAge(23);
        studentBuilder.addCourse(0,course1);
        studentBuilder.addCourse(1,course2);
        StudentProto.student student = studentBuilder.build();

        // proto对象
        System.out.println("The student object is: \n" + student);
        // 序列化
        byte[] studentByte = student.toByteArray();
        System.out.println("The student after encode is:\n" + Arrays.toString(studentByte));
        try {
            // 反序列化
            StudentProto.student newStudent = StudentProto.student.parseFrom(studentByte);
            System.out.println("The student after decode is:\n" + newStudent);
            // 转换json
            System.out.println("The student json format is:\n" + JsonFormat.printer().print(student));
        } catch (InvalidProtocolBufferException e) {
            e.printStackTrace();
        }
    }
}

运行结果如下:


The student object is: 
name: "Lucy"
age: 23
course {
  name: "Java"
  score: 99
}
course {
  name: "Python"
  score: 98
}

The student after encode is:
[10, 4, 76, 117, 99, 121, 16, 23, 26, 8, 10, 4, 74, 97, 118, 97, 16, 99, 26, 10, 10, 6, 80, 121, 116, 104, 111, 110, 16, 98]
The student after decode is:
name: "Lucy"
age: 23
course {
  name: "Java"
  score: 99
}
course {
  name: "Python"
  score: 98
}

The student json format is:
{
  "name": "Lucy",
  "age": 23,
  "course": [{
    "name": "Java",
    "score": 99
  }, {
    "name": "Python",
    "score": 98
  }]
}

Process finished with exit code 0

至此,proto基本的使用就已经结束了,实际也是将对象通过模板的方式去定义,以便于通过不同的语言去调用,并且从反序列化的过程中获取。

以上为个在实践过程中的一些操作,如有错误之处,请指出,欢迎讨论,共同进步!谢谢!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Protobuf在java中的简单使用实例 的相关文章

随机推荐

  • c++ 数据结构——树

    1 树概念 暂略 2 树的相关题目 2 1 leetcode 104 Maximum Depth of Binary Tree Definition for a binary tree node struct TreeNode int va
  • 谈谈软件行业面试

    原贴地址 http blog csdn net demowolf article details 5598966 我今天第一天正儿八经写博客 文思如泉涌 得多说几句废话 工作这么多年 面试无数次 从刚开始的技术雏儿 到现在的自我感觉良好 面
  • Java中间件(1)--分布式系统&中间件从入门到精通(五)

    上篇文章说了 当业务数据量大的时候 可以考虑业务和数据分离 当还解决不了的时候 可以考虑把数据库读写分离 缓存 还可以考虑把表垂直拆分 水平拆分 大型网站架构 2 分布式系统 中间件从入门到精通 四 中间件为软件应用提供了操作系统所提供的服
  • OpenStack2

    OpenStack2 1 DashBoard 2 私有网络 构建完整云主机 3 块存储服务 1 DashBoard 安装软件包 编辑配置文件 重启服务 网页成功访问使用网页 创建网络 换到 admin用户 切换到demo用户 创建云主机 创
  • Visual Studio 2010 部署QT4.8.4

    做GUI界面的设计时 目前已不再拘泥于VS的MFC框架 有很多开源的工具 本例以QT与VS2010的整合为例 演示环境搭建 后续将会用QT做VT的开发工作 第一步 下载QT和QT与VS的插件 在VS2010下以及结合VTK的情况 网络上经网
  • 让 Home 页面离开的时候保持原来的状态

    思路 1 用 keep alive 让页面不要销毁
  • 对有验证码的后台网页进行爆破-captcha-killer-modified

    对有验证码的后台网页进行爆破 captcha killer modified 实例 以pikachu靶场为目标 攻击目标url http xxxx pikachu master vul burteforce bf server php xx
  • PAT B1072 开学寄语

    算法思想 用数组标记应要查缴的物品mark 物品编号 1 在输入学生信息的同时判断该物品是否要查缴 因格式问题用了另一个数组保存该学生要查缴的物品编码 最后再输出该学生的名字和查缴物品编号 后来看了柳神的代码 不用这么麻烦 直接在输出前加括
  • HDU2085核反应堆

    Time Limit 1000 1000 MS Java Others Memory Limit 32768 32768 K Java Others Total Submission s 22891 Accepted Submission
  • PID控制原理说明与图解

    PID是比例 积分 微分的简称 一般常用于温度 速度等标量的控制 应用PID控制的系统存在对这些数值进行感测的传感器 又存在一个设定的目标值 这一种系统称为闭环控制系统 closed loop control system 系统中三个数值的
  • 工作能力构架框架图——我对工作的理解

    工作架构图 最近对工作内容进行了一次review 归纳如下 做简单地分享 job层 job层是我们最容易理解的一层 即我们平时的工作title 可能是销售 售前 产品等等 那么做产品的人能不能做售前呢 我想 肯定可以 因为在人力资源市场上
  • 解决eclipse出现launch failed,binary not found 的问题

    解决eclipse出现launch failed binary not found 的问题 仅作为解决问题的记录 问题描述 1 之前一直用eclipse写C 文件 后面学了java就用eclipse写了一些 java文件 但是偶然一次想要再
  • ValueError: column index (256) not an int in range(256)

    pandas 保存为xls时最大列为256 改为保存csv格式可避免该限制 解决方法 pd DataFrame in shp pre to csv 各区站点 file 14 17 csv
  • 软件开发管理参考网站

    BDD http en wikipedia org wiki Behavior Driven Development Scrum http zh wikipedia org zh Scrum UserCase http www hudong
  • Kubernetes 资源管理:最大化集群性能

    今天是 DevOps云学堂 与你共同进步的第 54天 Kubernetes 资源管理是部署和管理容器化应用程序的一个关键方面 它允许管理员控制系统不同部分之间计算资源的分配 例如CPU 内存和存储 有效的资源管理可确保应用程序获得正确运行所
  • Latex 字体的设置

    一 字体族的设置 1 说明 1 字体命令 textrm Roman Family 在花括号内的字体都是Roman Family 字体 2 字体声明 rmfamily Roman Family 该命令下面的字体都是是Roman Family字
  • Vim几种跳转方式

    Vim几种跳转方式 ps 以下时我常用的一些跳转指令 用于参考和复习记忆 还有一些后续会更新 文件内跳转 移动光标 普通模式下左h 右l 上k 下j 可以使用数字 hlkj 实现跳跃式移动 字符间跳转 跳转到当前字符的前面 普通模式下i 跳
  • CesiumJS三维案例

    WebGL近几年越来越被人们所关注 但是二三维开发难度也比普通web要高出许多 不管我们是在在开发或者是学习过程中 往往需要耗费大量的时间去查阅资料和研究官方案例 让本来就非常紧张的而宝贵的精力卷到了不关紧要的地方 而大多二三维的包 ope
  • apk文件结构解析一

    Apk文件用WINRAR压缩软件解压缩后 如下图所示 主要是三个文件 lib META INF res 和三个文件夹 AndroidManifest xml classes dex resources arsc 用工具展开可以看到如下所示的
  • Protobuf在java中的简单使用实例

    TTprotobuf是一种跨语言的数据转换协议 由google开源的 已支持大部份语言 在一般的数据交互过程中都是使用json xml等来做数据的转换 这其中涉及复杂的解析与序列化反序列化问题 如果在大量数据并发请求时 也会导致性能问题 p