聊一聊 gRPC 中的拦截器

article/2025/8/19 13:44:50

今天我们继续 gRPC 系列。

前面松哥跟大家聊了 gRPC 的简单案例,也说了四种不同的通信模式,感兴趣的小伙伴可以戳这里:

  1. 一个简单的案例入门 gRPC

  1. 聊一聊 gRPC 的四种通信模式

今天我们来继续聊一聊 gRPC 中的拦截器。

有请求的发送、处理,当然就会有拦截器的需求,例如在服务端通过拦截器统一进行请求认证等操作,这些就需要拦截器来完成,今天松哥先和小伙伴们来聊一聊 gRPC 中拦截器的基本用法,后面我再整一篇文章和小伙伴们做一个基于拦截器实现的 JWT 认证的 gRPC。

gRPC 中的拦截器整体上来说可以分为两大类:

  1. 服务端拦截器

  1. 客户端拦截器

我们分别来看。

1. 服务端拦截器


服务端拦截器的作用有点像我们 Java 中的 Filter,服务端拦截器又可以继续细分为一元拦截器流拦截器

一元拦截器对应我们上篇文章中所讲的一元 RPC,也就是一次请求,一次响应这种情况。

流拦截器则对应我们上篇文章中所讲的服务端流 RPC、客户端流 RPC 以及双向流 RPC。

不过,在 Java 代码中,无论是一元拦截器还是流拦截器,代码其实都是一样的。不过如果你是用 Go 实现的 gRPC,那么这块是不一样的。

所以接下来的内容我就不去区分一元拦截器和流拦截器了,我们直接来看一个服务端拦截器的例子。

这里我就不从头开始写了,我们直接在上篇文章的基础之上继续添加拦截器即可。

服务端拦截器工作位置大致如下:

从这张图中小伙伴们可以看到,我们可以在服务端处理请求之前将请求拦截下来,统一进行权限校验等操作,也可以在服务端将请求处理完毕之后,准备响应的时候将响应拦截下来,可以对响应进行二次处理。

首先我们来看请求拦截器,实际上是一个监听器:

publicclassBookServiceCallListener<R> extendsForwardingServerCallListener<R> {privatefinal ServerCall.Listener<R> delegate;publicBookServiceCallListener(ServerCall.Listener<R> delegate) {this.delegate = delegate;}@Overrideprotected ServerCall.Listener<R> delegate() {return delegate;}@OverridepublicvoidonMessage(R message) {System.out.println("这是客户端发来的消息,可以在这里进行预处理:"+message);super.onMessage(message);}
}
复制代码

这里我们自定义一个类,继承自 ForwardingServerCallListener 类,在这里重写 onMessage 方法,当有请求到达的时候,就会经过这里的 onMessage 方法。如果我们需要对传入的参数进行验证等操作,就可以在这里完成。

再来看看响应拦截器:

publicclassBookServiceCall<ReqT,RespT> extendsForwardingServerCall.SimpleForwardingServerCall<ReqT,RespT> {protectedBookServiceCall(ServerCall<ReqT, RespT> delegate) {super(delegate);}@Overrideprotected ServerCall<ReqT, RespT> delegate() {returnsuper.delegate();}@Overridepublic MethodDescriptor<ReqT, RespT> getMethodDescriptor() {returnsuper.getMethodDescriptor();}@OverridepublicvoidsendMessage(RespT message) {System.out.println("这是服务端返回给客户端的消息:"+message);super.sendMessage(message);}
}
复制代码

小伙伴们可能发现了,我这里用到了很多泛型,请求类型和响应类型都不建议指定具体类型,因为拦截器可能会拦截多种类型的请求,请求参数和响应的数据类型都不一定一样。

这里是重写 sendMessage 方法,在这个方法中我们可以对服务端准备返回给客户端的消息进行预处理。

所以这个位置就相当于响应拦截器

最后,我们需要在启动服务的时候,将这两个拦截器配置进去,代码如下:

publicvoidstart()throws IOException {intport=50051;server = ServerBuilder.forPort(port).addService(ServerInterceptors.intercept(newBookServiceImpl(), newServerInterceptor() {@Overridepublic <ReqT, RespT> ServerCall.Listener<ReqT> interceptCall(ServerCall<ReqT, RespT> call, Metadata headers, ServerCallHandler<ReqT, RespT> next) {StringfullMethodName= call.getMethodDescriptor().getFullMethodName();System.out.println(fullMethodName + ":pre");Set<String> keys = headers.keys();for (String key : keys) {System.out.println(key + ">>>" + headers.get(Metadata.Key.of(key, ASCII_STRING_MARSHALLER)));}returnnewBookServiceCallListener<>(next.startCall(newBookServiceCall(call), headers));}})).build().start();Runtime.getRuntime().addShutdownHook(newThread(() -> {BookServiceServer.this.stop();}));
}
复制代码

这是我之前服务启动的方法,以前我们调用 addService 方法的时候,直接添加对应的服务就可以了,现在,我们除了添加之前的 BookServiceImpl 服务之外,还额外给了一个拦截器。

每当请求到达的时候,就会经过拦截器的 interceptCall 方法,这个方法有三个参数:

  • 第一个参数 call 是消费传入的 RPC 消息的一个回调。

  • 第二个参数 headers 则是请求的消息头,如果我们通过 JWT 进行请求校验,那么就从这个 headers 中提取出请求的 JWT 令牌然后进行校验。

  • 第三个参数 next 就类似于我们在 Java 过滤器 filter 中的 filterChain 一样,让这个请求继续向下走。

在这个方法中,我们请求头的信息都打印出来给小伙伴们参考了。然后在返回值中,将我们刚刚写的请求拦截器和响应拦截器构建并返回。

好啦,这样我们的服务端拦截器就搞好啦~无论是一元的 RPC 消息还是流式的 RPC 消息,都会经过这个拦截器,响应也是一样。

2. 客户端拦截器


客户端拦截器就比较简单了,客户端拦截器可以将我们的请求拦截下来,例如我们如果想为所有请求添加统一的令牌 Token,那么就可以在这里来做,方式如下:

ManagedChannelchannel= ManagedChannelBuilder.forAddress("localhost", 50051).usePlaintext().intercept(newClientInterceptor() {@Overridepublic <ReqT, RespT> ClientCall<ReqT, RespT> interceptCall(MethodDescriptor<ReqT, RespT> method, CallOptions callOptions, Channel next) {System.out.println("!!!!!!!!!!!!!!!!");callOptions = callOptions.withAuthority("javaboy");return next.newCall(method,callOptions);}}).build();
BookServiceGrpc.BookServiceStubstub= BookServiceGrpc.newStub(channel);
复制代码

当我们的请求执行的时候,这个客户端拦截器就会被触发。

3. 小结


好啦,今天就和小伙伴们简单介绍一下服务端拦截器和客户端拦截器。下篇文章,松哥会通过一个 JWT 认证来和小伙伴们演示这个拦截器的具体用法。


http://chatgpt.dhexx.cn/article/L2pk8rXm.shtml

相关文章

聊一聊微博新知博主这件事,看看赚钱方式有哪些?

从今天开始&#xff0c;准备将我付费星球内的精华文章&#xff0c;在每周六和周日以付费文章的方式在公众号分享给大家&#xff0c;如果你不想加入我的星球&#xff0c;还想看的话&#xff0c;可以在这里付费看。当然&#xff0c;加入星球会更划算&#xff0c;因为星球内内容更…

【QGIS入门实战精品教程】2.1:初识QGIS软件

从今天开始&#xff0c;我们一起来学习一款免费开源、对机器要求低、功能强大的GIS软件&#xff1a;QGIS &#xff01; 一、QGIS简介 QGIS&#xff08;原称Quantum GIS&#xff09;是一个自由软件的桌面GIS软件。它提供数据的显示、编辑和分析功能。 QGIS是一个用户界面友好的…

QGIS教程01:为什么要用QGIS?

从去年开始抛弃ArcGIS转用QGIS以来&#xff0c;发现QGIS越来越好用&#xff0c;功能也相当强大。而且我发现身边好多朋友也在开始使用QGIS&#xff0c;但目前国内这方面的学习资料还比较少&#xff0c;国外的原版资料又相对比较啰嗦&#xff0c;所以我和几位GISer入门知识星球的…

qgis教程

qgis教程 一、导入点云文件 1、新建图层 2、视图-》创建3d视图 3、添加标注工具&#xff0c;创建 shape

【QGIS入门实战精品教程】3.4:QGIS创建、连接、打包GeoPackage数据库及数据入库案例详解

GeoPackage(以下简称gpkg),内部使用SQLite实现的一种单文件、与操作系统无关的地理数据库。在QGIS中可以很方便的实现GeoPackage的创建与连接等操作。 文章目录 一、QGIS创建GeoPackage1. 创建数据库2. 数据入库二、矢量数据打包为GeoPackage1. 加载shp文件2. 使用QGIS打包图…

【QGIS入门实战精品教程】3.3:QGIS如何打开ArcGIS创建的文件数据库(GDB)?

在行业应用中,GIS地理空间数据往往存储在ESRI ArcGIS的文件地理数据库(File GeodataBase),因此,ArcGIS与QGIS的数据交互、共享就显得非常重要。QGIS3可以直接打开File GDB数据,并对数据进行显示、查看、处理等操作。具体的步骤如下: 相关阅读:【QGIS入门实战精品教程】3…

【QGIS入门实战精品教程】1.2:QGIS与ArcGIS的区别和联系

「刘一哥GIS」系列专栏《QGIS入门实战精品教程(配套案例数据)》目录 以下是GISGeography官方给出的两者之间的27点比较(译): 官方网址:https://gisgeography.com/qgis-arcgis-differences/ 1.QGIS容纳更多的数据格式 ArcGIS没有支持所有的数据格式,毫无疑问,QGIS在处…

Qgis教程1:添加在线地图

自学Qgis小结1 一、作为应届生小白&#xff0c;进入公司得知要学习Qgis&#xff0c;可谓是对此一点也不了解&#xff0c;从来没接触过Qgis的我也不得不沉下心来去学习&#xff0c;取取经&#xff0c;下面是我学习Qgis过程的一点理解&#xff0c;希望对广大网友有所帮助&#x…

【QGIS入门实战精品教程】5.2:QGIS自定义坐标系案例教程

我国全国版图常用的投影为双标准纬线圆锥投影,如等积Albers投影或者等角Lambert投影,所使用的地理坐标参照系则依据数据生产时间而有所不同,如早期的北京54坐标系和西安80坐标系,以及近年来所普遍采用的国家2000大地坐标系。本文以全国四百万基础植被数据所采用的Albers投影…

【QGIS入门实战精品教程】14.1:QGIS如何加载各种在线地图?

文章目录 一、XYZ Tiles连接方式二、插件添加三、WMS/WMTS/OWS连接方式一、XYZ Tiles连接方式 1. 加载OpenStreetMap QGIS默认可以加载OpenStreetMap地图。在左侧点击XYZ Tiles,默认下面有个OpenStreetMap选项,双击打右侧会显示地图,如下图所示: 在OpenStreetMap上右键→…

【QGIS入门实战精品教程】2.2:QGIS软件的下载与安装(Windows)

文章目录 一、QGIS下载二、QGIS安装​一、QGIS下载 QGIS软件官网下载地址:https://www.qgis.org/en/site/ 进入官网之后,点击【Download Now】进入下载页面: 选择对应的版本进行下载: 开始下载:

QGIS基础教程 (入门级)——高程、光谱数据设置伪彩色

QGIS基础教程&#xff08;一&#xff09; 本教程内容相对基础&#xff0c;面向从未使用过QGIS或相似GIS软件人群 数据分享&#xff0c;百度网盘链接: https://pan.baidu.com/s/1Qi-o2TNoxPIdX0bWgqZzcQ?pwdathz 提取码: athz 第二节 遥感影像基础操作——1. 高程数据设置彩色…

QGIS基础教程 (入门级)——下载安装、新建工程、加载数据

QGIS基础教程&#xff08;一&#xff09; 本教程内容相对基础&#xff0c;面向从未使用过QGIS或相似GIS软件人群 第一节 QGIS下载安装&#xff0c;新建工程&#xff0c;加载数据 1. 下载及安装 官网下载&#xff1a;QGIS下载网址 注意&#xff1a;下载长期版&#xff0c;比…

【QGIS入门实战精品教程】1.1:QGIS与GIS的区别和联系

「刘一哥GIS」系列专栏《QGIS入门实战精品教程(配套案例数据)》目录 1. QGIS概述 QGIS(在2.0版本之前称之为Quantum GIS)于2002年由Gary Sherman创立,在2007年由OSGeo接管,并于2009年发布了1.0版本,目前最高版本为3.22。QGIS采用开源证书GNU GPLv2 (GNU General Public…

QGIS基础教程——QGIS工具箱找不到了|工具箱如何打开

QGIS工具箱找不到了|工具箱如何打开 工具箱不见了&#xff0c;像这样 解决方法&#xff1a; 1.打开【数据处理】 查看菜单栏是否有【地理处理】菜单&#xff0c;有直接跳到步骤2 若没有&#xff0c;点击菜单栏【插件】——【管理并安装插件】 点击【已安装】&#xff0c;在…

QGIS使用之基本介绍和安装教程

今天&#xff0c;小崇想和大家介绍一下QGIS的基本知识。希望我们互相学习&#xff0c;共同进步&#xff01; 何为QGIS&#xff1f; QGIS&#xff08;Quantum GIS&#xff09;是一款免费的桌面GIS软件&#xff0c;可运行在Linux、Unix、Mac OSX和Windows等平台。QGIS是基于Qt…

QGIS Server安装教程

1. 简述 关于QGIS Server相关的文档真的很少&#xff0c;国内也只有几篇关于QGIS Server安装的教程&#xff0c;而且随着QGIS的更新&#xff0c;这些教程逐步落后不再适用。 这篇教程使用的是当前长期稳定版本QGIS3.10&#xff0c;只适合当前版本&#xff0c;后期QGIS不断更新可…