springBoot+protobuf(全程Protocol Buffers协议)简单入门

  1. 了解Protocol Buffers协议
    Protocal Buffers是google推出的一种序列化协议,用于结构化的数据序列化、反序列化。
    官方解释:Protocol Buffers 是一种语言无关、平台无关、可扩展的序列化结构数据的方法,它可用于(数据)通信协议、数据存储等。Protocol Buffers 是一种灵活,高效,自动化机制的结构数据序列化方法。可类比 XML,但是比 XML 更小(3 ~ 10倍)、更快(20 ~ 100倍)、更为简单。
  2. 为什么要使用protobuf
    使用protobuf的原因肯定是为了解决开发中的一些问题,那使用其他的序列化机制会出现什么问题呢?

(1)java默认序列化机制:效率极低,而且还能不能跨语言之间共享数据。

(2)XML常用于与其他项目之间数据传输或者是共享数据,但是编码和解码会造成很大的性能损失。

(3)gson格式也是常见的一种,但是gson在解析的时候非常耗时,而且gson结构非常占内存。

但是我们protobuf是一种灵活的、高效的、自动化的序列化机制,可以有效的解决上面的问题。由于 protobuf是跨语言的,所以用不同的语言序列化对象后,生成一段字节码,之后可以其他任何语言反序列化并自用,大大方便了跨语言的通讯,同时也提高了效率

3.protobuf常见数据类型与Java对照表
在这里插入图片描述

  1. 语法类型讲解,创建user_login.proto文件
syntax = "proto3";//声明版本 syntax=”proto3”,如果没有声明,则默认是proto2.option java_package = "com.test.proto";//指定生成的类应该放在什么Java包名下.
option java_outer_classname = "MessageUserLogin";//定义应该包含这个文件中所有类的类名,调用时MessageUserLogin.MessageUserLoginRequest 或者 MessageUserLogin.MessageUserLoginResponse.
option java_multiple_files = false;//生成的类是否应该放在一个单独的Java文件里,是否需要將生成的类拆分为多个.默认false,可以不写.message MessageUserLoginRequest {//message对应java的class/** 字段编号在 Protocol Buffers (protobuf) 中,每个字段都必须有一个唯一的标识符,这个标识符是一个整数,称为字段编号(Field Number)。字段编号用于在序列化和反序列化过程中唯一地识别一个字段,即使在不同版本的协议中字段的顺序发生变化,只要字段编号不变,就可以保证数据的一致性和正确性。字段编号的范围是1到2^29-1,但是通常建议将字段编号保持在1到1500之间,以避免冲突。字段编号不能重复,否则编译器会报错。字段编号的选择也会影响序列化后的二进制数据的大小和性能,较小的字段编号会导致更小的二进制数据和更快的序列化/反序列化速度,但这种影响通常可以忽略不计。在实际开发中,我们通常根据字段的重要性和出现的频率来选择字段编号,例如将重要的、经常使用的字段编号设置得较小。*/string a = 1;   //string 数据类型 a字段名 1字段编号int32 b = 2;int64 c = 3;bool d = 4;double e = 5;float f = 6;repeated string g = 7; //repeated 对应java的List集合 repeated string g = List<String> gmap<string, string> h = 8;//map 对应java的Map集合repeated MessageUserLoginResponse i = 9;//集合对象 repeated MessageUserLoginResponse i = List<MessageUserLoginResponse> gmap<string, MessageUserLoginResponse> j = 10;//map对象MessageUserLoginResponse k = 11;//嵌套对象字段
}message MessageUserLoginResponse {string a = 1;int32 b = 2;int64 c = 3;bool d = 4;double e = 5;float f = 6;
}
  1. 如何将.proto文件生成java文件,目前简单介绍一个窗口生成的。idea工具生成后续追加
    下载protoc.exe编辑器
    下载链接: 下载地址
    根据同样的系统选择不同的编译器就ok,我用的windows, 所以选择 :protoc-3.11.0-win64.zip
    下载后只用到bin里面的protoc.exe
  2. SpringBoot使用protobuf格式的接口
    建立SpringBoot项目,pom.xml需要引用内容如下:
    根据自己项目实际情况添加,我的springBoot版本是2.7.17,springBoot版本这里比较重要,
    因为后边在模拟Content-Type=application/x-protobuf请求时,是要配置我们服务端能请求类型内容。
    Spring Boot 2.6及更高版本中,配置方式是不同的。
    根据自己项目实际情况添加
    根据自己项目实际情况添加
    根据自己项目实际情况添加
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.7.17</version><relativePath/><!--  lookup parent from repository  --></parent><!--  Generated by https://start.springboot.io  --><!--  优质的 spring/boot/data/security/cloud 框架中文文档尽在 => https://springdoc.cn  --><groupId>com.game.module</groupId><artifactId>GameModule</artifactId><version>0.0.1-SNAPSHOT</version><name>GameModule</name><description>GameModule</description><url/><licenses><license/></licenses><developers><developer/></developers><scm><connection/><developerConnection/><tag/><url/></scm><properties><java.version>1.8</java.version></properties><dependencies><!--springBoot相关--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><!--springBoot相关--><dependency><groupId>org.json</groupId><artifactId>json</artifactId><version>20240303</version><!--  使用最新的版本或适合你项目的版本  --></dependency><!--protobuf相关--><dependency><groupId>com.google.protobuf</groupId><artifactId>protobuf-java</artifactId><version>3.11.0</version></dependency><dependency><groupId>com.google.protobuf</groupId><artifactId>protobuf-java-util</artifactId><version>3.11.0</version></dependency><dependency><groupId>com.googlecode.protobuf-java-format</groupId><artifactId>protobuf-java-format</artifactId><version>1.2</version></dependency><!--protobuf相关--><!-- 网络请求依赖 --><dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpclient</artifactId><version>4.5.2</version></dependency><dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpcore</artifactId><version>4.4</version></dependency><!-- 网络请求依赖 --><!-- 工具类 --><dependency><groupId>org.apache.commons</groupId><artifactId>commons-lang3</artifactId><version>3.0</version></dependency><dependency><groupId>commons-collections</groupId><artifactId>commons-collections</artifactId><version>3.0</version></dependency><!-- 工具类 --><!-- websocket --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId></dependency><!-- websocket --><!-- lombok --><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.30</version></dependency><!-- lombok --></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><version>2.6.2</version><configuration><fork>true</fork><mainClass>com.game.module.gamemodule.GameModuleApplication</mainClass></configuration><executions><execution><goals><goal>repackage</goal></goals></execution></executions></plugin><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><configuration><source>1.8</source><target>1.8</target><encoding>UTF-8</encoding></configuration></plugin></plugins><resources><resource><directory>src/main/java</directory><includes><include>**/*.xml</include></includes><!--  是否替换资源中的属性  --><filtering>false</filtering></resource><resource><directory>src/main/resources</directory><filtering>true</filtering><includes><include>*</include></includes></resource></resources></build>
</project>

编写.proto文件,user_login.proto 内容如下:

syntax = "proto3";option java_package = "com.boomsecret.protobuf";
option java_outer_classname = "MessageUserLogin";message MessageUserLoginRequest {string username = 1;string password = 2;
}message MessageUserLoginResponse {string access_token = 1;string username = 2;
}
  1. 生成java代码:
    我的做法是将下载好的protoc.exe放在项目里面了,这样我直接在项目路径下cmd进去好找位置,你也可以不放。
    在这里插入图片描述
    然后进入protoc.exe存方位cmd进去执行命令。
    示例: .\center\user_login.proto 是你的.proto文件所在路径 --java_out=./ 指定生成文件的路径
    大家根据实际情况自行修改,我的是在同一级所以.\user_login.proto
.\protoc.exe .\user_login.proto --java_out=./

在这里插入图片描述
在这里插入图片描述
强调下你的项目路径就是你.proto里面指定的option java_package = 路径
8.编写protobuf格式的Controller接口:

package com.example.protobuf.demo.controller;import com.boomsecret.protobuf.MessageUserLogin;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import util.HttpUtils;import java.net.URI;
import java.util.UUID;@Controller
public class TestController {@RequestMapping(value = "/demo/test", produces = "application/x-protobuf")@ResponseBodypublic MessageUserLogin.MessageUserLoginResponse getPersonProto(@RequestBody MessageUserLogin.MessageUserLoginRequest request) {MessageUserLogin.MessageUserLoginResponse.Builder builder = MessageUserLogin.MessageUserLoginResponse.newBuilder();builder.setAccessToken(UUID.randomUUID().toString()+"_res");builder.setUsername(request.getUsername()+"_res");return builder.build();}}

编写测试HttpUtils模拟application/x-protobuf

package util;import com.google.protobuf.GeneratedMessageV3;
import com.googlecode.protobuf.format.JsonFormat;
import org.apache.http.Header;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.InputStreamEntity;
import org.apache.http.impl.client.HttpClients;import java.io.ByteArrayInputStream;
import java.io.IOException;public class HttpUtils {public static HttpResponse doPost(HttpPost post, GeneratedMessageV3 message) throws IOException {HttpClient httpclient = HttpClients.createDefault();String requestUrl = post.getURI().toString();ByteArrayInputStream inputStream = new ByteArrayInputStream(message.toByteArray());InputStreamEntity inputStreamEntity = new InputStreamEntity(inputStream);post.setEntity(inputStreamEntity);post.addHeader("Content-Type", "application/x-protobuf");for (Header header : post.getAllHeaders()) {System.out.println(header.getName() + ":" + header.getValue());}StringBuilder sb = new StringBuilder();sb.append("curl -XPOST ");for (Header header : post.getAllHeaders()) {sb.append(" -H \"").append(header.getName()).append(":").append(header.getValue()).append("\"");}String jsonBody = JsonFormat.printToString(message);jsonBody = jsonBody.replace("\"", "\\\"");sb.append(" -d \"").append(jsonBody).append("\"");sb.append(" ").append(requestUrl);System.out.println(sb.toString());return httpclient.execute(post);}
}

编写测试接口

package com.game.module.gamemodule.controller;import com.game.module.gamemodule.proto.MessageUserLogin;
import com.game.module.gamemodule.utils.HttpUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;import java.net.URI;
import java.util.Arrays;
import java.util.UUID;@Slf4j
@RestController
public class UserLoginController {@RequestMapping(value = "/demo/test", produces = "application/x-protobuf")@ResponseBodypublic MessageUserLogin.MessageUserLoginResponse getPersonProto(@RequestBody MessageUserLogin.MessageUserLoginRequest request) {MessageUserLogin.MessageUserLoginResponse.Builder builder = MessageUserLogin.MessageUserLoginResponse.newBuilder();String token = UUID.randomUUID().toString() + "_res";builder.setAccessToken(token);String name = request.getUsername() + "_res";builder.setUsername(name);return builder.build();//序列化}@RequestMapping(value = "/userTest")public void test() {try {URI uri = new URI("http", null, "localhost", 9101, "/demo/test", "", null);HttpPost request = new HttpPost(uri);MessageUserLogin.MessageUserLoginRequest.Builder builder = MessageUserLogin.MessageUserLoginRequest.newBuilder();builder.setUsername("tom");builder.setPassword("123456");log.info("序列化后的内容:{}", Arrays.toString(builder.build().toByteArray()));HttpResponse response = HttpUtils.doPost(request, builder.build());// builder.build() 序列化MessageUserLogin.MessageUserLoginResponse messageUserLoginResponse = MessageUserLogin.MessageUserLoginResponse.parseFrom(response.getEntity().getContent());//parseFrom 反序列化log.info("请求结果反序列化后:{}", messageUserLoginResponse.toString());} catch (Exception e) {System.out.println("请求异常");}}}

以debug方式运行SpringBoot项目,并在controller加断点,然后运行测试代码: 访问http://localhost:9101/userTest 接口
在这里插入图片描述
此时我们会看到415,表示错误org.springframework.web.HttpMediaTypeNotSupportedException表明服务器不支持你的客户端尝试使用的application/x-protobuf;charset=UTF-8这种内容类型。这通常发生在服务器只处理特定的媒体类型,而application/x-protobuf不在这些类型中时。此时就要配置服务端支持protobuf,就与上面我们的springboot版本配置相关,我的springBoot版本是2.7.17。Spring Boot 2.6及更高版本中,配置方式是不同的。
添加MessageConverterConfig,2.6以上配置

package com.game.module.gamemodule.config;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.protobuf.ProtobufHttpMessageConverter;@Configuration
public class MessageConverterConfig {@Beanpublic ProtobufHttpMessageConverter protobufHttpMessageConverter() {return new ProtobufHttpMessageConverter();}
}

2.6以下配置方式

   @Configurationpublic class WebConfig implements WebMvcConfigurer {@Overridepublic void extendMessageConverters(List<HttpMessageConverter<?>> converters) {converters.add(new ProtobufHttpMessageConverter());}}

再次执行就可以了
在这里插入图片描述
可以看到请求过来的数据是正确的,放行后可以看到响应数据也是正确的:
在这里插入图片描述

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

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

相关文章

鸿蒙(API 12 Beta2版)NDK开发【使用Node-API接口进行异步任务开发】

使用Node-API接口进行异步任务开发 场景介绍 napi_create_async_work是Node-API接口之一&#xff0c;用于创建一个异步工作对象。可以在需要执行耗时操作的场景中使用&#xff0c;以避免阻塞主线程&#xff0c;确保应用程序的性能和响应性能。例如以下场景&#xff1a; 文件…

入门 PyQt6 看过来(案例)17~ 表格

PyQt6提供了两种用于有规律地呈现更多数据的控件&#xff0c;一种是表格结构的控件(QTableView)&#xff0c;另一种是树形结构的控件(QTreeView)。表格控件属于QTableView类&#xff0c;QTableWidget继承于QTableView。 1 QTableView 表格控件 QTableView控件中QStandItemMod…

IT人求职就业手册:如何在数字时代脱颖而出

&#x1f482; 个人网站:【 摸鱼游戏】【网址导航】【神级代码资源网站】&#x1f91f; 一站式轻松构建小程序、Web网站、移动应用&#xff1a;&#x1f449;注册地址&#x1f91f; 基于Web端打造的&#xff1a;&#x1f449;轻量化工具创作平台&#x1f485; 想寻找共同学习交…

【CodinGame】趣味算法(教学用) CLASH OF CODE -20240731

文章目录 正文闰年偶数和密码塔楼高度 写在最后END 正文 闰年 import sys import math# Auto-generated code below aims at helping you parse # the standard input according to the problem statement.a int(input()) b int(input()) count0 for i in range(a, b 1):if…

DELL服务器RAID配置详细教程

DELL服务器RAID配置教程 在启动电脑的时候按CTRLR 进入 RAID 设置见面如下图 名称解释&#xff1a; Disk Group&#xff1a;磁盘组&#xff0c;这里相当于是阵列&#xff0c;例如配置了一个RAID5&#xff0c;就是一个磁盘组 VD(Virtual Disk)&#xff1a; 虚拟磁盘&#xff…

开启智能开发的新纪元:探索 GPT-4o mini 模型的无限可能

引言 随着人工智能技术的飞速发展&#xff0c;大型语言模型已成为推动软件开发和创新的关键力量。OpenAI 最新发布的 GPT-4o mini 模型以其卓越的性能和极具竞争力的价格&#xff0c;为开发者社区带来了新的活力。本文将探讨 GPT-4o mini 模型的特性&#xff0c;以及它如何帮助…

K8S第二节:kubeadm搭建K8s集群

上回书说到什么是K8s&#xff0c;这回就在我自己的虚拟机上搭建一个K8s集群; 一、安装K8S需要的软件包 yum install -y kubelet-1.23.1 kubeadm-1.23.1 kubectl-1.23.1 其中&#xff1a; kubelet:是K8s集群中每个node节点上的管家&#xff0c;用来处理Master节点下发到本节点的…

深入源码:解析SpotBugs (5)BugReportor

常见的 Bug 定位后&#xff0c;通过 bugReport的reportBug&#xff08;BugInstance&#xff09; 方法&#xff0c;将bug 发布出来。 一般的 Detector 经检测后会调用 bugReportor.reportBug 方法或者 BugAccumulator.accumulateBug 。 在GUI中&#xff0c;分析结束后会在下框…

楼宇智能化仿真实训室解决方案

在信息技术的浪潮中&#xff0c;智慧城市作为未来城市发展的新形态&#xff0c;正以前所未有的速度在全球范围内兴起。其中&#xff0c;楼宇智能化作为智慧城市的关键构成&#xff0c;扮演着举足轻重的角色。它不仅提升了建筑的能源效率、安全性与舒适度&#xff0c;还促进了城…

WIFI7:引领智能驾驶新未来

近年来&#xff0c;智能驾驶技术飞速发展&#xff0c;从最初的初级的辅助驾驶逐步迈向高度自动驾驶&#xff0c;这一变化历程深刻依赖的是高效、稳定且前沿的无线通信技术的支撑。WIFI7&#xff0c;作为无线通信领域的最新里程碑&#xff0c;凭借其前所未有的性能提升与功能拓展…

这些才是电脑该装的,5款软件良心且实用,别让它们寒心

为什么别人的电脑&#xff0c;开机无广告&#xff0c;使用0卡顿&#xff0c;下载资源快的飞起&#xff0c;网页就是简洁画面。 而自己的电脑却.....开机超过1%&#xff0c;广告一大堆&#xff0c;下载速度差之千里&#xff0c;网页全是“是兄弟&#xff0c;就来砍我”的船新版…

奥运会被误报的韩国国旗,有多少AI能准确识别?结果出人意料!

大家好&#xff0c;我是木易&#xff0c;一个持续关注AI领域的互联网技术产品经理&#xff0c;国内Top2本科&#xff0c;美国Top10 CS研究生&#xff0c;MBA。我坚信AI是普通人变强的“外挂”&#xff0c;专注于分享AI全维度知识&#xff0c;包括但不限于AI科普&#xff0c;AI工…

飞创直线模组桁架机械手优势及应用领域

随着工业自动化和智能制造的发展&#xff0c;直线模组桁架机械手极大地减轻了人类的体力劳动负担&#xff0c;在危险性、重复性高的作业环境中展现出了非凡的替代能力&#xff0c;引领着工业生产向自动化、智能化方向迈进。 一、飞创直线模组桁架机械手优势 飞创直线模组桁架…

Spring Boot集成udp通讯

Spring Boot集成udp通讯 加入依赖编辑配置文件配置相关属性具体业务类客户端调试 加入依赖 <!--加入UDP通信所需依赖--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-integration</artifactId&…

【PCB设计原则5】-PCB设计的寄生元件

寄生电容 在PCB上布两条靠近的走线&#xff0c;很容易形成寄生电容。由于这种电容的存在&#xff0c;在一条走线上的快速电压变化&#xff0c;可在另一条走线上产生电流信号。 设计电路板时&#xff0c;放置两条彼此靠近的走线就会产生寄生电容。例如,在不同的两层&#xff0c…

OJ-0731

题目 题解 参考 import java.util.Arrays; import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner scanner new Scanner(System.in);while (scanner.hasNext()) {int xmh scanner.nextInt();int n scanner.nextInt();int[] COs …

SFP, SFP+,QSFP光模块封装类型

前言&#xff1a; 本文是自己对SFP, SFP,QSFP光模块封装类型的学习记录&#xff0c;所有的资料都搜集字引用链接里的博客内容&#xff0c;本文更多的是自己的学习笔记记录所以可能会有一些理解错误&#xff0c;请更多的参考引用链接里的信息来源。 引用&#xff1a; 认识SFP/SF…

Arduino Mega 2560开发板的引脚分配图及说明,以及链接can的方法

与Arduino Uno相比,Arduino Mega2560的资源就丰富多了,它具有54个数字I/O口(其中14个可提供PWM输出),16个模拟I/O口,4对串行数据通信口(UART),一个复位开关,一个ICSP下载口,支持USB接口和直流电源供电,具体的资源分配见下图。 Arduino Mega 2560开发板的引脚分配…

nginx代理设置时能获取到源IP地址的方法

nginx通过http_x_forwarded_for限制来访IP示例_ngnix 根据header的x-forwarded-for限制接入-CSDN博客 名称ip客户端地址10.0.23.90nginx服务器地址110.0.202.48:18888&#xff0c;代理到10.0.204.82:8888nginx服务器地址210.0.204.82:8888&#xff0c;代理到10.0.204.82:8887后…

Yarn UI 时间问题,相差8小时

位置 $HADOOP_HOME/share/hadoop/yarn/hadoop-yarn-common-2.6.1.jar 查看 jar tf hadoop-yarn-common-2.6.1.jar |grep yarn.dt.plugins.js webapps/static/yarn.dt.plugins.js 解压 jar -xvf hadoop-yarn-common-2.6.1.jar webapps/static/yarn.dt.plugins.js inflated: we…