【SpringBoot3】结合 gRpc 通过 proto文件生成Java代码

news2024/12/23 18:57:20

一、什么是protobuf

Protobuf(Protocol Buffers)是由Google开发的一种灵活、高效、自动化的结构化数据序列化方法,类似于XML、JSON等,但更小、更快、更简单。它主要用于网络通信和数据存储等场景,广泛应用于各种编程语言中。

Protobuf的作用主要体现在以下几个方面:

  1. 数据序列化与反序列化
    Protobuf可以将数据结构或对象序列化为一个二进制流,同时也可以将这个二进制流反序列化回原始数据结构。这种序列化方式相比于传统的文本格式(如XML、JSON)更加高效,因为它采用了二进制格式,减少了存储空间和网络传输的带宽消耗。

  2. 跨语言通信
    Protobuf支持多种编程语言,包括C++、Java、Python等。这意味着在不同编程语言编写的程序之间,可以使用Protobuf格式进行高效的数据交换和通信。

  3. 向后兼容性
    Protobuf设计时就考虑到了向后兼容性。当数据结构发生变化时(例如添加新的字段),旧的程序仍然可以读取由新程序序列化的数据,忽略新增的字段。

  4. 自动化处理
    Protobuf编译器(protoc)可以根据.proto文件(定义数据结构的文本文件)自动生成对应语言的源代码,这些源代码提供了序列化、反序列化以及数据访问的方法,极大地简化了开发过程。

二、基本使用步骤

1、在pom.xml中添加编译插件和相关依赖

<properties>
<!--<os.detected.classifier>windows-x86_64</os.detected.classifier>-->
    <protobuf-maven-plugin.version>0.6.1</protobuf-maven-plugin.version>
    <protoc.version>3.25.3</protoc.version>
    <protobuf.java.version>3.25.3</protobuf.java.version>
    <grpc-java.version>1.64.0</grpc-java.version>
</properties>

//...//
<dependencies>
    <dependency>
        <groupId>com.google.protobuf</groupId>
        <artifactId>protobuf-java</artifactId>
        <version>${protobuf.java.version}</version>
    </dependency>
    <dependency>
        <groupId>com.google.protobuf</groupId>
        <artifactId>protobuf-java-util</artifactId>
        <version>${protobuf.java.version}</version>
    </dependency>
</dependencies>
// ... //

<build>
    <pluginManagement>
        <plugins>
            <!-- protobuf-maven-plugin -->
            <plugin>
                <groupId>org.xolstice.maven.plugins</groupId>
                <artifactId>protobuf-maven-plugin</artifactId>
                <version>${protobuf-maven-plugin.version}</version>
                <extensions>true</extensions>
                <executions>
                    <execution>
                        <id>protoc-compile</id>
                        <phase>generate-sources</phase>
                        <goals>
                            <goal>compile</goal>
                            <goal>compile-custom</goal>
                        </goals>
                    </execution>
                    <execution>
                        <id>protoc-test-compile</id>
                        <phase>generate-test-sources</phase>
                        <goals>
                            <goal>test-compile</goal>
                            <goal>test-compile-custom</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <protocArtifact>
                        com.google.protobuf:protoc:${protoc.version}:exe:${os.detected.classifier}
                    </protocArtifact>
                    <attachProtoSources>true</attachProtoSources>
                    <useArgumentFile>true</useArgumentFile>
                    <writeDescriptorSet>false</writeDescriptorSet>
                    <attachDescriptorSet>false</attachDescriptorSet>
                    <includeDependenciesInDescriptorSet>false</includeDependenciesInDescriptorSet>
                    <checkStaleness>true</checkStaleness>
                    <pluginId>grpc-java</pluginId>
                    <pluginArtifact>
                        io.grpc:protoc-gen-grpc-java:${grpc-java.version}:exe:${os.detected.classifier}
                    </pluginArtifact>
                    <protocPlugins>
                    </protocPlugins>
                </configuration>
            </plugin>
        </plugins>
    </pluginManagement>
    <plugins>
        <plugin>
            <groupId>org.xolstice.maven.plugins</groupId>
            <artifactId>protobuf-maven-plugin</artifactId>
        </plugin>
    </plugins>
</build>

2、在工程目录src/main/proto目录中创建 person.proto

插件固定编译src/main/proto.proto文件,所以文件必须放在这里

syntax = "proto3";

option java_package = "com.demo.proto";
option java_multiple_files = true;
option java_outer_classname = "UserProto";

message User {
  string name = 1;
  string email = 2;
  int32 age = 3;
}

参数说明

  • java_package:生成的Java文件对应的包名
  • java_multiple_files:将实体、proto、builder类放在不同文件中
  • java_outer_classname:指定生成的proto文件名称,如果没指定就是OuterClass结尾(如UserOuterClass)

3、执行 Maven compile 编译工程生成代码

插件会根据proto文件自动在target/classes目录中生成Java文件

  • com.demo.proto.User
  • com.demo.proto.UserOrBuilder
  • com.demo.proto.UserProto
    在这里插入图片描述

4、编写测试类

public class UserProtoTest {
    @Test
    public void test() throws InvalidProtocolBufferException {
        User.Builder builder = User.newBuilder();
        builder.setName("jacky");
        builder.setAge(30);
        builder.setEmail("jacky@example.com");
        User user = builder.build();

        // 序列化
        byte[] serializedUser = user.toByteArray();

        // 反序列化
        Person deserializedUser = Person.parseFrom(serializedUser);
        System.out.println("--------deserialized--------");
        System.out.println(deserializedUser);
    }
}

执行结果如下:

--------deserialized--------
name: "jacky"
email: "jacky@example.com"
age: 30

三、proto文件,字段类型和java类的对照

在Protocol Buffers(简称Proto)中,消息字段类型与Java类型之间存在一定的对应关系。以下是一个表格,列出了Proto中的常见消息字段类型及其在Java中的对应类型:

Proto字段类型Java类型备注
doubledouble双精度浮点数
floatfloat单精度浮点数
int32int使用可变长度编码,对于有符号整数,如果你的字段可能包含负数,则建议使用sint32
sint32int使用可变长度编码,有符号整数
uint32int使用可变长度编码,无符号整数
int64long使用可变长度编码,对于有符号整数,如果你的字段可能包含负数,则建议使用sint64
sint64long使用可变长度编码,有符号整数
uint64long使用可变长度编码,无符号整数
fixed32int总是4个字节,如果数值总是比2^28大的话,这个类型会比uint32更高效
fixed64long总是8个字节,如果数值总是比2^56大的话,这个类型会比uint64更高效
sfixed32int总是4个字节
sfixed64long总是8个字节
boolboolean布尔值
stringString字符串,UTF-8编码
bytesByteString字节序列

注意:

  1. 对于整数类型,Proto中的int32int64类型在Java中分别对应intlong类型,但由于Java没有无符号整数类型,因此在使用时需要注意。对于有符号整数且可能包含负值的情况,建议使用sint32sint64类型,它们在编码时会处理符号位。

  2. fixed32fixed64类型分别总是占用4个字节和8个字节的空间,无论其实际值的大小如何。这在某些情况下可以提高编码效率,特别是当你知道数值范围时。

  3. sfixed32sfixed64类型也分别占用固定的4个字节和8个字节空间,但它们用于有符号整数。

  4. string类型在Java中对应String类,而bytes类型则对应ByteString类,后者是Protobuf提供的一个专门用于处理字节序列的类。

四、proto文件语法

.proto文件,用于定义数据结构和服务接口。以下是.proto文件的语法详解:

1. 文件结构

.proto文件由一系列定义组成,包括语法声明、包声明、导入声明、消息类型定义、枚举类型定义、服务接口定义以及选项声明。

2. 语法声明

语法声明用于指定.proto文件使用的Proto版本。例如:

syntax = "proto3";

目前常用的版本有proto2proto3,其中proto3是更现代、更简洁的语法。

3. 包声明

包声明用于指定.proto文件中定义的类型所属的命名空间。例如:

package example;

在Proto中,包名用于避免不同.proto文件中定义的类型之间的名称冲突。

4. 导入声明

导入声明用于导入其他.proto文件中定义的类型。例如:

import "other_proto_file.proto";

导入声明使得当前.proto文件可以使用其他文件中定义的消息类型、枚举类型和服务接口。

5. 消息类型定义

消息类型定义用于定义数据结构。例如:

message Person {
  string name = 1;
  int32 id = 2;
  string email = 3;
}

在消息类型定义中,每个字段都有一个类型、一个名称和一个唯一的编号。字段编号用于在序列化过程中识别字段。

6. 枚举类型定义

枚举类型定义用于定义一组命名的整数常量。例如:

enum PhoneType {
  MOBILE = 0;
  HOME = 1;
  WORK = 2;
}

枚举类型中的每个常量都有一个名称和一个整数值。第一个枚举值的整数值必须为0。

7. 服务接口定义

服务接口定义用于定义RPC(远程过程调用)方法。例如:

service AddressBook {
  rpc GetPerson(Person) returns (Person);
}

在服务接口定义中,每个RPC方法都有一个请求类型、一个响应类型和一个方法名。请求类型和响应类型都是之前定义的消息类型。

8. 选项声明

选项声明用于设置文件级别的选项,如生成代码的特定语言设置。例如:

option java_package = "com.example.proto";
option java_outer_classname = "ProtoExample";
option java_multiple_files = true;

这些选项影响生成的代码,如Java代码的包名和外部类名。

总结

.proto文件的语法相对简单,主要由一系列定义组成。通过定义消息类型、枚举类型和服务接口,.proto文件描述了数据的结构和服务的接口。然后,可以使用Proto编译器将这些定义编译成各种语言的代码,以便在应用程序中使用。

参考

  • https://protobuf.com.cn/overview/
  • https://protobuf.dev/getting-started/javatutorial/
  • https://protobuf.dev/reference/java/java-generated/
  • https://protobuf.dev/programming-guides/proto3/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1898857.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Android - 模拟器

Android SDK 包括一个在您的计算机上运行的虚拟移动设备模拟器。 该模拟器可让您在不使用物理设备的情况下对 Android 应用程序进行原型设计、开发和测试。 在本章中&#xff0c;我们将探索真实安卓设备中存在的模拟器中的不同功能。 创建 AVD 如果您想模拟真实设备&#xff0c…

vue3使用echarts和Pixi.js打造一个令人惊叹的3D图在线展示

本文由ScriptEcho平台提供技术支持 项目地址&#xff1a;传送门 基于 Pixi.js 的动态图形渲染技术 应用场景介绍 Pixi.js 是一款功能强大的 2D 渲染引擎&#xff0c;可用于创建交互式图形、游戏和动画。它因其高性能、可扩展性和跨平台兼容性而受到开发者的欢迎。本代码示例…

博奥龙/2024年部分高分文献及引用试剂展示

01IF&#xff1a;50.5标题7-Dehydrocholesterol dictates ferroptosis sensitivityDOI10.1038/s41586-023-06983-9期刊Nature引用试剂BF03008HRP-山羊抗兔IgG(HL)02IF&#xff1a;14.7标题Aggresome formation promotes ASK1/JNK signaling activation and stemness maintenanc…

海南云亿商务咨询有限公司专业电商团队值得信赖

在当今数字化浪潮下&#xff0c;电商行业蓬勃发展&#xff0c;抖音作为短视频领域的佼佼者&#xff0c;更是为电商行业带来了全新的机遇。海南云亿商务咨询有限公司凭借对市场的敏锐洞察和丰富的经验积累&#xff0c;专注于抖音电商服务&#xff0c;致力于为广大企业和个人提供…

【24年一博研讨会总结】BJ0705

1.工艺边据PCB边缘 >5mm. 2.IPC-A-600G Pitch < 1.25mm H<0.025mm,小于0.4mm,取消丝印框&#xff0c;防止锡膏不匀虚焊&#xff1b; 3.表面镀金与镍厚度 金厚度 um镍厚度 um0.0192.7830.0213.3610.0453.6640.0314.378 4.多层板&#xff0c;层间距>20mil 可以认…

国内外AI大模型价格一览

海外AI大模型&#xff0c;以OpenAI、Google等大厂商为主。 国内AI大模型的价格 海外较国内还是一个量级的价格差&#xff0c;相信年底还会有一波降价&#xff0c;至到达到普惠的条件。

多特征线性回归

目录 一、多特征符号意义说明&#xff1a;二、多特征模型表示&#xff1a;三、Numpy向量表示、内积计算&#xff1a;1.向量表示&#xff1a;2.内积计算&#xff1a; 四、多元线性回归梯度下降算法&#xff1a; 一、多特征符号意义说明&#xff1a; x下标j&#xff1a;表示第j个…

c++ 构造,析构,拷贝,移动构造函数

文章目录 概述1.构造函数2. 拷贝构造函数3.移动构造函数4.析构函数 例子QTUE4/5 c 小结 概述 对于c来说&#xff0c;最基础的是类。对于一个类来说&#xff0c;主要由以下函数构成。如下&#xff1a; 构造函数拷贝构造函数移动构造函数析构函数 当然&#xff0c;还有一个操作…

API字符串

API&字符串 文章目录 API&字符串API&#xff08;Application Programming Interface&#xff09;&#xff1a;简单理解&#xff1a;已经学习过的APIAPI帮助文档 字符串String&#xff0c;StringBuilder&#xff0c;StringJonierString概述注意点创建String对象的两种方…

项目一 nfs 共享服务器 Haproxy 代理 Keepalive 高可用集群

深入理解程序的数据存储 配置NFS服务器 配置ansible环境

Chatopera 聊天机器人讲师班 第一季,传授制作有趣有用的聊天机器人 | Chatopera

课程亮点 传授制作有趣有用的聊天机器人 课程直播时间 2024 年 07 月 03 日 ~ 07 月 09 日 上课形式 使用腾讯会议直播授课&#xff0c;可回放观看视频。 课程大纲 时间课程07 月 03 日 10:00 AM ~ 11:00 AM第一章 为什么要学习定制聊天机器人&#xff1f;07 月 03 日 1…

Robot Framework

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、pandas是什么&#xff1f;二、使用步骤 1.引入库2.读入数据总结 前言 提示&#xff1a;这里可以添加本文要记录的大概内容&#xff1a; 例如&#xff1a;…

微信小程序的校园点餐系统-计算机毕业设计源码56979

摘 要 近年来&#xff0c;随着移动互联网的迅猛发展&#xff0c;微信小程序作为一种轻量级应用形式逐渐受到人们的关注和喜爱。在此背景下&#xff0c;各行各业开始向微信小程序上线他们的服务&#xff0c;其中包括餐饮行业&#xff0c;在校园内&#xff0c;学生、教职工和访客…

基于docker的prometheus+grafana+altermanager+prometheus-webhook-dingtalk钉钉报警

一、各软件功能简介 prometheus&#xff1a;Prometheus(是由go语言(golang)开发)是一套开源的监控&报警&时间序列数 据库的组合。主要优点&#xff1a;外部依赖安装使用超简单、系统集成 多等 grafana&#xff1a;Grafana 是一款采用 go 语言编写的开源应用&#xff0…

redis学习(005 java客户端 RedisTemplate学习)

黑马程序员Redis入门到实战教程&#xff0c;深度透析redis底层原理redis分布式锁企业解决方案黑马点评实战项目 总时长 42:48:00 共175P 此文章包含第16p-第p23的内容 文章目录 java客户端jedisSpringDataRedis项目实现hash哈希操作 java客户端 jedis 测试 ps:如果连接不上&…

PLC基础知识

1.PLC中的数据寄存器地址D表示存数据的地方。 2.PLC的物理存储器的规定&#xff1a;PLC存储器以字节为单位&#xff08;Byte&#xff09;&#xff0c;存储单元以位&#xff08;Bit&#xff09;、字节&#xff08;B&#xff0c;8Bit&#xff09;、字&#xff08;W&#xff0c;1…

jenkins搭建部署前端工程 ,从0到1

一.java环境配置 1 安装tomcatjdk17 这个也行 3 安装maven3.3.9 安装教程参考 4 安装Jenkins 下载地址 参考教程 二、相关配置 1 访问http://localhost:8080/jenkins&#xff0c;进入Jenkins初始化页面&#xff0c;第一次启动时间可能有点长&#xff0c;耐心等待。进入成功后会…

软考《信息系统运行管理员》-2.5信息系统运维管理系统与专用工具

2.5信息系统运维管理系统与专用工具 信息系统运维管理系统功能框架 信息系统运维管理系统是站在运维管理的整体视角&#xff0c;基于运维流程&#xff0c;以服务为导向的业务 服务管理和运维管理支撑平台&#xff0c;提供统一管理门户&#xff0c;最终帮助运维对象实现信息系…

(2024)KAN: Kolmogorov–Arnold Networks:评论

KAN: Kolmogorov–Arnold Networks: A review 公和众与号&#xff1a;EDPJ&#xff08;进 Q 交流群&#xff1a;922230617 或加 VX&#xff1a;CV_EDPJ 进 V 交流群&#xff09; 目录 0. 摘要 1. MLP 也有可学习的激活函数 2. 标题的意义 3. KAN 是具有样条基激活函数的 M…

代码随想录算法训练营第四十四天|188.买卖股票的最佳时机IV、309.最佳买卖股票时机含冷冻期、714.买卖股票的最佳时机含手续费

188.买卖股票的最佳时机IV 题目链接&#xff1a;188.买卖股票的最佳时机IV 文档讲解&#xff1a;代码随想录 状态&#xff1a;不会 思路&#xff1a; 在股票买卖1使用一维dp的基础上&#xff0c;升级成二维的即可。 定义dp[k1][2]&#xff0c;其中 dp[j][0] 表示第j次交易后持…