OKHttp拦截器解析
OKHttp涉及到拦截器大概的执行步骤为:
1.通过newCall生成RealCall对象
具体代码如下:
@Override public Call newCall(Request request) {return new RealCall(this, request, false /* for web socket */);}
2.调用Call的execute方法
当然这也可以是执行异步任务的enqueue方法,我们这里主要分析execute方法,在这个方法中调用getResponseWithInterceptorChain()从而调用拦截器。
具体代码如下:
/*** 同步执行网络请求并返回响应** @return 返回响应对象* @throws IOException 如果在执行请求过程中发生I/O错误*/@Override public Response execute() throws IOException {// 同步锁,确保同一时间只有一个线程执行该方法synchronized (this) {// 检查是否已经执行过,如果已经执行过则抛出异常if (executed) throw new IllegalStateException("Already Executed");// 标记为已执行executed = true;}// 捕获调用栈信息,用于调试和错误追踪captureCallStackTrace();try {// 将当前请求添加到调度器中,以便管理和执行client.dispatcher().executed(this);// 通过拦截器链获取响应Response result = getResponseWithInterceptorChain();// 如果响应为空,则抛出异常if (result == null) throw new IOException("Canceled");// 返回响应return result;} finally {// 请求完成后,从调度器中移除当前请求client.dispatcher().finished(this);}}
3.调用拦截器,处理相关拦截操作(责任链模式)
/*** 通过拦截器链获取响应** @return 返回响应对象* @throws IOException 如果在获取响应过程中发生I/O错误*/Response getResponseWithInterceptorChain() throws IOException {// 构建一个完整的拦截器栈List<Interceptor> interceptors = new ArrayList<>();// 添加应用程序提供的拦截器interceptors.addAll(client.interceptors());// 添加重试和重定向拦截器interceptors.add(retryAndFollowUpInterceptor);// 添加桥接拦截器,用于处理请求和响应的头部信息interceptors.add(new BridgeInterceptor(client.cookieJar()));// 添加缓存拦截器,用于处理缓存interceptors.add(new CacheInterceptor(client.internalCache()));// 添加连接拦截器,用于建立网络连接interceptors.add(new ConnectInterceptor(client));// 如果不是WebSocket请求,添加网络拦截器if (!forWebSocket) {interceptors.addAll(client.networkInterceptors());}// 添加调用服务器拦截器,用于发送请求和接收响应interceptors.add(new CallServerInterceptor(forWebSocket));// 创建一个拦截器链Interceptor.Chain chain = new RealInterceptorChain(interceptors, null, null, null, 0, originalRequest);// 执行拦截器链并返回响应return chain.proceed(originalRequest);}
4.拦截器执行,链式调用
核心类为:RealInterceptorChain
public final class RealInterceptorChain implements Interceptor.Chain {private final List<Interceptor> interceptors;private final StreamAllocation streamAllocation;private final HttpCodec httpCodec;private final RealConnection connection;private final int index;private final Request request;private int calls;public RealInterceptorChain(List<Interceptor> interceptors, StreamAllocation streamAllocation,HttpCodec httpCodec, RealConnection connection, int index, Request request) {this.interceptors = interceptors;this.connection = connection;this.streamAllocation = streamAllocation;this.httpCodec = httpCodec;this.index = index;this.request = request;}@Override public Connection connection() {return connection;}public StreamAllocation streamAllocation() {return streamAllocation;}public HttpCodec httpStream() {return httpCodec;}@Override public Request request() {return request;}// 这个是拦截器中执行的proceed方法@Override public Response proceed(Request request) throws IOException {return proceed(request, streamAllocation, httpCodec, connection);}public Response proceed(Request request, StreamAllocation streamAllocation, HttpCodec httpCodec,RealConnection connection) throws IOException {...// Call the next interceptor in the chain.// 传入下一个拦截器的索引和拦截器List,生成RealInterceptorChain对象RealInterceptorChain next = new RealInterceptorChain(interceptors, streamAllocation, httpCodec, connection, index + 1, request);// 根据当前索引获取拦截器Interceptor interceptor = interceptors.get(index);// 我们的拦截器实现了intercept(chain)方法,通过intercept实现了调用拦截器链的操作Response response = interceptor.intercept(next);... return response;}
}
具体我们实现拦截器的简单例子如下:
public class CustomHeaderInterceptor implements Interceptor {@Overridepublic Response intercept(Chain next) throws IOException {Request originalRequest = next.request();// 添加自定义头部信息Request newRequest = originalRequest.newBuilder().header("Custom-Header", "Custom-Value").build();// 继续处理请求,我们可以看到,Response response = interceptor.intercept(next)传下来的next在这里执行了proceed方法。从而实现了链式调用return next.proceed(newRequest);}
}相关文章:
OKHttp拦截器解析
OKHttp涉及到拦截器大概的执行步骤为: 1.通过newCall生成RealCall对象 具体代码如下: Override public Call newCall(Request request) {return new RealCall(this, request, false /* for web socket */);}2.调用Call的execute方法 当然这也可以是执…...
STM32标准库移植RT-Thread nano
STM32标准库移植RT-Thread Nano 哔哩哔哩教程链接:STM32F1标准库移植RT_Thread Nano 移植前的准备 stm32标准库的裸机代码(最好带有点灯和串口)RT-Thread Nano Pack自己的开发板 移植前的说明 本人是在读学生,正在学习阶段&a…...
c++11总结26——std::regex
std::regex 是 C11 引入的 正则表达式库,用于 字符串匹配、搜索和替换。 🔹 头文件:#include <regex> 🔹 命名空间:std 🔹 支持的匹配模式:ECMAScript(默认)、POS…...
langchain教程-12.Agent/工具定义/Agent调用工具/Agentic RAG
前言 该系列教程的代码: https://github.com/shar-pen/Langchain-MiniTutorial 我主要参考 langchain 官方教程, 有选择性的记录了一下学习内容 这是教程清单 1.初试langchain2.prompt3.OutputParser/输出解析4.model/vllm模型部署和langchain调用5.DocumentLoader/多种文档…...
leetcode_双指针 125.验证回文串
125.验证回文串 如果在将所有大写字符转换为小写字符、并移除所有非字母数字字符之后,短语正着读和反着读都一样。则可以认为该短语是一个回文串 。 字母和数字都属于字母数字字符。 给你一个字符串 s,如果它是回文串 ,返回 true ÿ…...
ML.NET库学习001:基于PCA的信用卡异常检查之样本处理与训练
文章目录 (文末提供数据集下载)ML.NET库学习001:基于PCA的信用卡异常检查之样本处理与训练目标项目概述代码结构概述1. **主要类和文件**2. **命名空间和使用指令**3. **数据类 (TransactionObservation)**4. **主程序入口 (Main 方法)**5. **数据预处理 (DataPrepr…...
【华为OD机考】华为OD笔试真题解析(1)--AI处理器组合
一、题目描述 某公司研发了一款高性能AI处理器,每台物理设备具备8颗AI处理器,编号分别为0、1、2、3、4、5、6、7。 编号0~3的处理器处于同一链路中,编号4~7的处理器处于另外一个链路中,不同链路中的处理器不能通信,如…...
edu小程序挖掘严重支付逻辑漏洞
edu小程序挖掘严重支付逻辑漏洞 一、敏感信息泄露 打开购电小程序 这里需要输入姓名和学号,直接搜索引擎搜索即可得到,这就不用多说了,但是这里的手机号可以任意输入,只要用户没有绑定手机号这里我们输入自己的手机号抓包直接进…...
力扣 279. 完全平方数
🔗 https://leetcode.cn/problems/perfect-squares 题目 给你一个整数 n ,返回 和为 n 的完全平方数的最少数量完全平方数可以拆解为两个相同数的乘积 思路 dp 公式,就是从看用哪个完全平方数 1 2 4 9…… 到当前 sum 的数量最少 代码 …...
鸿蒙生态潮起:开发者的逐浪之旅
鸿蒙生态潮起:开发者的逐浪之旅 在全球科技的澎湃浪潮中,鸿蒙生态宛如一座正在崛起的新大陆,熠熠生辉,吸引着无数开发者扬帆起航,探寻其中蕴藏的无限机遇,也直面诸多挑战。 鸿蒙生态的机遇,首先…...
Diskgenius系统迁移之后无法使用USB启动
前言 本文用于记录系统迁移中遇到的问题及解决方法,如有不对请指出,谢谢! 现象 使用DiskGenius进行系统迁移后,使用USB启动失败,反复在品牌logo和黑屏之间切换,期间还会在左上角显示”reset system“报错…...
Kafka 可靠性探究—副本刨析
Kafka 的多副本机制提升了数据容灾能力。 副本通常分为数据副本与服务副本。数据副本是指在不同的节点上持久化同一份数据;服务副本指多个节点提供同样的服务,每个节点都有能力接收来自外部的请求并进行相应的处理。 1 副本刨析 1.1 相关概念 AR&…...
我的博文天地测试报告
我的博文天地测试报告 文章目录 我的博文天地测试报告 一.项目背景 二.项目功能 2.1 功能介绍 三.测试分类 3.1 功能测试 3.1.1 测试用例 3.1.2 实际执行测试的部分操作步骤/结果的截图 3.2 自动化测试 3.3 性能测试 3.1.2 用户登录 jmeter性能测试结果 性能测试遇到的困难 …...
EtherCAT主站IGH-- 35 -- IGH之pdo_list.h/c文件解析
EtherCAT主站IGH-- 35 -- IGH之pdo_list.h/c文件解析 0 预览一 该文件功能`pdo_list.c` 文件功能函数预览二 函数功能介绍`pdo_list.c` 中主要函数的作用1. `ec_pdo_list_init`2. `ec_pdo_list_clear`3. `ec_pdo_list_clear_pdos`4. `ec_pdo_list_total_size`5. `ec_pdo_list_a…...
嵌入式开发神器:Buildroot的介绍和使用方法
目录 引言**Buildroot 能做什么?****1. 生成交叉编译工具链(Toolchain)****2. 生成嵌入式 Linux 根文件系统(RootFS)****3. 编译 Linux 内核和设备树文件****4. 编译 Bootloader(U-Boot)****5. …...
JavaScript系列(61)--边缘计算应用开发详解
JavaScript边缘计算应用开发详解 🌐 今天,让我们深入探讨JavaScript的边缘计算应用开发。边缘计算是一种将计算和数据存储分布到更靠近数据源的位置的架构模式,它能够提供更低的延迟和更好的实时性能。 边缘计算基础架构 🌟 &am…...
【LeetCode】day15 142.环形链表II
142. 环形链表 II - 力扣(LeetCode) 题目描述 给定一个链表的头节点 head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。 如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则…...
代理对象与目标对象
1. 定义:代理对象和目标对象 1.1 目标对象(Target Object) 目标对象是指 被增强的原始对象,即需要通过 AOP 切面(Aspect)增强功能的业务对象(原始类)。增强逻辑(Advice…...
【Kubernetes Pod间通信-第3篇】Kubernetes中Pod与ClusterIP服务之间的通信
引言 我们之前了解了在不同场景下,Kubernetes中Pod之间的通信是如何路由的。 【Kubernetes Pod间通信-第1篇】在单个子网中使用underlay网络实现Pod到Pod的通信【Kubernetes Pod间通信-第2篇】使用BGP实现Pod到Pod的通信现在,我们来看看在集群中,Pod与服务之间的通信是如何…...
DNN(深度神经网络)近似 Lyapunov 函数
import torch import torch.nn as nn import torch.optim as optim import matplotlib.pyplot as plt # from torchviz import make_dot import torchviz# 1. Lyapunov 函数近似器(MLP 结构) class LyapunovNet(nn.Module):def __init__(self, input_dim…...
新手也能看懂的TCAD入门:用Sentaurus和Silvaco分别跑一个NPN三极管(附完整代码)
TCAD新手实战指南:从零开始仿真NPN三极管 1. 初识TCAD:半导体仿真的利器 在微电子领域,TCAD(Technology Computer-Aided Design)工具如同设计师的"数字实验室",让我们能在计算机上模拟半导体器件…...
基于Adafruit FLORA的红外遥控胸针DIY:从嵌入式编程到可穿戴艺术
1. 项目概述:一个藏在时尚配饰里的“电视终结者”几年前,我在一个朋友聚会上,发现大家明明在聊天,眼睛却总是不自觉地瞟向角落里那个正在播放无聊广告的电视。直接走过去关掉显得有点突兀,找遥控器又太麻烦。那一刻我就…...
从0到1:手把手教你搭建VSCode(附避坑指南,拒绝报错),全程复制粘贴即可
🔥个人主页:北极的代码(欢迎来访) 🎬作者简介:java后端学习者 ❄️个人专栏:苍穹外卖日记,SSM框架深入,JavaWeb ✨命运的结局尽可永在,不屈的挑战却不可须臾或…...
开源技能库构建指南:Git+Markdown+Docsify打造个人技术知识体系
1. 项目概述:一个开源技能库的诞生与价值在技术领域,尤其是软件开发、运维和数据分析等方向,我们每天都在与海量的工具、框架和命令打交道。时间一长,一个很现实的问题就摆在了面前:那些曾经花了好几个小时才调通的复杂…...
解锁Midjourney V6黑白摄影隐藏指令:5个未公开--stylize与--sref协同技法,92%用户至今不会用
更多请点击: https://intelliparadigm.com 第一章:Midjourney V6黑白摄影的美学本质与技术觉醒 黑白摄影在 Midjourney V6 中已超越简单的色彩剥离,成为一场基于对比度张力、纹理显影与光影叙事的深度建模重构。V6 的隐式扩散架构强化了灰阶…...
Linux磁盘挂载与开机自启配置
Linux磁盘挂载与开机自启配置磁盘挂载是 Linux 存储管理中的基础操作。很多线上问题都与挂载配置有关,例如重启后数据盘没挂上、路径指向错误分区、应用因挂载点缺失而启动失败。中级阶段不仅要会临时挂载,更要理解永久挂载的配置方式和风险控制。一、先…...
量化交易性能优化:高性能内存管理与计算加速实践
1. 项目概述与核心价值最近在量化交易社区里,一个名为Lexus2016/turbo_quant_memory的项目引起了我的注意。乍一看这个标题,它融合了几个非常吸引人的关键词:“Turbo”(涡轮增压,意指加速)、“Quant”&…...
基于Particle Photon与NeoPixel的物联网徽章:实时追踪ISS空间站
1. 项目概述:一个会“感知”太空的智能徽章 如果你和我一样,对头顶那片星空充满好奇,特别是当得知国际空间站(ISS)这个重达数百吨的大家伙,其实每天都会数次悄无声息地掠过我们的城市上空时,总…...
AI智能体文件管理:从零构建统一资产仓库与版本控制系统
1. 项目概述与核心价值最近在折腾AI智能体开发的朋友,估计没少为文件管理这事儿头疼。你辛辛苦苦训练好的模型、精心设计的提示词模板、还有那些五花八门的配置文件,是不是散落在各个角落,每次想复现或者分享都得一通乱找?更别提团…...
用STM32F103C8T6和HC-05蓝牙模块,从零DIY一辆蓝牙遥控小车(附完整代码与MIT App Inventor教程)
从零打造STM32蓝牙遥控小车:硬件配置到APP开发全指南 项目背景与核心价值 对于嵌入式开发初学者来说,理论知识和实际项目之间往往存在一道难以跨越的鸿沟。而一个完整的硬件项目实践,恰恰是填补这一空白的最佳方式。基于STM32F103C8T6和HC-05…...
