今天项目中遇到需要将从push接收到的数据按照协议parse成应用层需要的结构化数据类型问题;因为push消息类型繁多,等待解析出的结构化数据类型也多样,有的还需要经过几步的parse过程;而且因为项目历史原因,使用Protocal Buffer(push的数据是字节形式的传递)。中间尝试了代理、装饰等模式,都失败了,最终还是使用了原始的继承解决问题;在解决问题个过程中也学习了下OkHttp中的拦截器实现,这里做简单记录:

  • ﷒拦截器的接口定义如下:

  

可以看到,在拦截器的回调中,我们可以拿到两个重要的参数Request和Response,而接口在回调时,会接收一个Chain类型的参数,这个参数保存了Request和Response的相关数据。

  • 看一个简单的Interceptor接口实现例子:

该拦截器实例的功能只是在请求发出前和接收到响应后,分别打印log。Response response=chain.proceed(request); 很重要,它是将拦截连串起来的关键。

  • 再看下,一个网络请求的应用吧:

跟进,OkHttpClient.Builder的addInterceptor()方法,可以看到,在OkHttp内部是使用了List保存了添加的所有拦截器。

  • 跟进client.newCall(request).execute();的执行过程,查看拦截器的串联过程:

从上面的方法中可以看到,请求默认会被构造成RealCall类型,再进一步查看RealCall的execute()方法:

上面的红色方框中这行代码,它并没有真正的执行网络请求,而只是简单地将请求放入请求池中,让它等待分派器的后续执行。而真正的执行体在上面的蓝色方框中,它封装了一个拦截器链(Chain),并调用了Chain的proced方法,传入原始的request对象,这里开始拦截器链的调用过程:

  • 查看proceed方法,可以看到,它使用循环+递归的方式,借助函数调用栈,将拦截器串联起来:

上面的代码中,真正执行网络请求的是最后一行绿色方框中的代码,而当存在多个拦截器时,每个拦截器在执行时都会在上图的蓝色方框中的代码地方阻塞,等待下一个拦截器的调用返回。

  • 为了说明清楚,下面分别以 拦截器链中有1个、2个拦截器的场景加以模拟:

OkHttp拦截器的实现原理的更多相关文章

  1. struts2拦截器的实现原理

    拦截器(interceptor)是Struts2最强大的特性之一,也可以说是struts2的核心,拦截器可以让你在Action和result被执行之前或之后进行一些处理.同时,拦截器也可以让你将通用的 ...

  2. struts2拦截器的实现原理及源码剖析

    拦截器(interceptor)是Struts2最强大的特性之一,也可以说是struts2的核心,拦截器可以让你在Action和result被执行之前或之后进行一些处理.同时,拦截器也可以让你将通用的 ...

  3. Okhttp拦截器统一异常处理并多次读取response.body().string()

    参考:https://blog.csdn.net/a624806998/article/details/73863606 引言: 写这篇文章,因为在自己编写实现Http日志拦截器的时候,在拦截器中使用 ...

  4. 从网络请求过程看OkHttp拦截器

    前言 之前我们结合设计模式简单说了下OkHttp的大体流程,今天就继续说说它的核心部分--拦截器. 因为拦截器组成的链其实是完成了网络通信的整个流程,所以我们今天就从这个角度说说各拦截器的功能. 首先 ...

  5. Java拦截器的实现原理

    对于某个类的A方法进行拦截,在A执行前插入一段代码,A执行后也插入一段代码 原理: 写个拦截器,拦截器中包含要插入前后执行的两段代码 interceptor { C();//C方法 D();//D方法 ...

  6. mybatis源码分析(5)-----拦截器的实现原理(动态代理+责任链)

    写在前面 MyBatsi 的拦截器模式是基于代理的代理模式.并且myBatis 的插件开发也是以拦截器的形式集成到myBatis 当中. MyBatis 的拦截器已经插件是在org.apache.ib ...

  7. Struts2_day04--课程介绍_Struts2拦截器概述&底层原理_重要的概念

    Struts2_day04 上节内容 今天内容 Struts2拦截器概述 拦截器底层原理 重要的概念 自定义拦截器 自定义登录拦截器 Struts2的标签库 Struts2表单标签(会用) Strut ...

  8. Android 开发 框架系列 OkHttp拦截器

    前言 此篇博客只讲解okhttp的拦截器功能的详细使用,如果你还不太了解okhttp可以参考我另外一篇博客 Android 开发 框架系列 OkHttp使用详解 添加Interceptor的简单例子 ...

  9. Spring 拦截器实现+后台原理(MethodInterceptor)

    MethodInterceptor MethodInterceptor是AOP项目中的拦截器(注:不是动态代理拦截器),区别与HandlerInterceptor拦截目标时请求,它拦截的目标是方法. ...

随机推荐

  1. leetcode414-第三大的数

    给定一个非空数组,返回此数组中第三大的数.如果不存在,则返回数组中最大的数.要求算法时间复杂度必须是O(n). 示例 1: 输入: [3, 2, 1] 输出: 1 解释: 第三大的数是 1. 示例 2 ...

  2. LeetCode 84. Largest Rectangle in Histogram 单调栈应用

    LeetCode 84. Largest Rectangle in Histogram 单调栈应用 leetcode+ 循环数组,求右边第一个大的数字 求一个数组中右边第一个比他大的数(单调栈 Lee ...

  3. jwplayer 隐藏属性方法记载

    jwplayer().getPosition(): //播放了多少秒 jwplayer('playerdiv').play(); || jwplayer(0).play(true / false); ...

  4. Java基础(十二):包(package)

    一.Java 包(package): 为了更好地组织类,Java 提供了包机制,用于区别类名的命名空间.包的作用: 1.把功能相似或相关的类或接口组织在同一个包中,方便类的查找和使用. 2.如同文件夹 ...

  5. window.open()页面之间函数传值

    项目中遇到的问题,使用window.open()开一个页面之后,cookie会消失,所以无法一键切肤不管作用,解决方案如下: window.open()总结: window.open("sU ...

  6. c++ placement new概念

    参考:http://www.cnblogs.com/Clingingboy/archive/2013/04/26/3044910.html 转:http://bbs.chinaunix.net/thr ...

  7. Redis自学笔记 --string类型

    string类型                                                                                  set 赋值 get ...

  8. 应用程序在状态栏展示时间(C#)

    private DispatcherTimer _timer; private void SetTimeElaspInStatusBar() { try { _timer = new Dispatch ...

  9. kettle利用参数遍历执行指定目录下的所有对象

    使用kettle设计ETL设计完成后,我们就需要按照我们业务的需要对我们设计好的ETL程序,ktr或者kjb进行调度,以实现定时定点的数据抽取,或者说句转换工作,我们如何实现调度呢? 场景:在/wor ...

  10. Spring -- 三种配置方式

    1.Explicit configuration in XML:显示的XML配置. 优点: 1)XML配置方式进一步降低了耦合,使得应用更加容易扩展,即使对配置文件进一步修改也不需要工程进行修改和重新 ...