首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

《OkHttp源码分析》之 OkHttp的请求拦截链

本文作者

感谢Mirs_sir为我们带来OkHttp源码分析系列文章,目录如下:

1.Http请求原理

2.OkHttp的简单使用

3.OkHttp的初始化

4.OkHttp请求流程分析

5.OkHttp的请求拦截链

6.OkHttp请求调度的分析

7.OkHttp的缓存管理

8.深入源码理解HashMap、LinkedHashMap,DiskLruCache

日更一篇,敬请期待哦

小编温馨提示:代码块向右滑动可查看更多代码,长按可复制代码哟

OkHttp的请求拦截链

OkHttp request interception chain

OkHttp请求的核心处理就是这一系列的拦截链

这里面看到 ,第一个add的是client里面自己定义的拦截链集合和如果不是webSocket的话能添加客户端网络的拦截链,然后后面依次添加的拦截器有

这种链式调用在设计模式里有个叫责任链模式,这个的话我们进去看下源码印证一下,因为他这个集合是一个带有泛型的,所以直接看他的泛型

然后再看RealInterceptorChain的代码因为后面调用的是他的proceed方法,可以知道他肯定是实现了Interceptor的Chain,我们先来看他的初始化的过程

直接看他的构造函数

为null的先不管,看那些不为null的, 传过来了一个请求链,index是0,还有request 接着调用了RealInterceptorChain的proceed方法

这里面可以看到最后调用的是proceed(Request request, StreamAllocation streamAllocation, HttpCodec httpCodec,RealConnection connection)

首先是几个判断,流程如下

httpCodec不为空并且connection的url不支持这个请求的Url,那么抛出异常

httpCodec不为空且当前的请求数大于1,抛出异常

开吃调用拦截链的逻辑

httpCodec不为空并且当前索引加1小于请求链的长度,下一个请求的call不为1 ,抛出异常。

response为空,抛出异常

return response

这块逻辑 会不停的去调用下一个

第一次运行到这里的时候,调用的是RetryAndFollowUpInterceptor这个拦截器的intercept方法

RetryAndFollowUpInterceptor 重试和跟进拦截器

之前有简单介绍过这个拦截器,所以我们直接看他的intercept方法

这边的流程屡一下

获取request

new 一个StreamAllocation

然后再去调用当前传过来的chain的proceed方法

然后返回response

组装response和一些善后处理

敏锐的我们看到了streamAllocation 按照字面的意思是 流分配 传入的值是连接池,url,和一个callStackTrace

SteamAllocation上面的描述我们看下,直接中文版翻译过来:

这个我们大致就知道了这个类是来干嘛的了,在RetryAndFollowUpInterceptor里面他只进行了 realease和streamFailed操作 ,推测他的调用应该在下一个拦截链里面,我们根据上面的拦截器集合知道 下一个调用的是BridgeInterceptor拦截器

BridgeInterceptor

这个拦截器主要的职责是

从应用程序代码到网络代码的桥梁。 首先,它根据用户请求构建网络请求。 然后它继续呼叫网络。 最后,它从网络响应中构建用户响应。 主要构件的是网络请求的header的部分和组装返回来的body

这个类不大,直接放上来讲

这里截止到调用下个拦截链的时候,做了以下几件事情:

构建请求体

设置content-type和content-length

设置Host

设置Connection

处理gzip

设置cookie

设置User-Agent

调用下一个拦截链

按照上面的顺序,下一个拦截链是CacheInterceptor,CacheInterceptor是个比较复杂的拦截链,如果我们没设置的话里面的判断都是不进去的,然后调用下一个chain,下一个是ConnectInterceptor

ConnectInterceptor

这个拦截器做的事情看起来简单,实际上是比较复杂的,他的主要职责是:

代码量很少

这里重要的就是streamAllocation这个类,这边调用了他的newStream()方法和connection()方法 ,我们点进去分析这两个方法

这里先初始化了几个时间 ,然后去find了一个健康的connection 返回RealConnection

我们看这个小蝌蚪找妈妈的方法

这个方法的参数有必要说明一下

doExtensiveHealthChecks = true //是否做健康检查 get的话不做

connectTimeout = 10000 //链接超时时间

readTimeout = 10000 //读取超时时间

writeTimeout = 10000 //写入超时时间

connectionRetryEnabled = true //连接重试启用

这个方法首先就是进入了一个while循环,里面又调用了一个findConnection的方法去寻找RealConnection,又转到findConnection,这个方法比较长,慢慢来看

这边寻找到一个连接后,讲这个链接赋值个一个RealConnection,然后去调用下一个链条的proceed方法,就是上面的

根据上面的集合 下一个链条是CallServerInterceptor,我们来进入CallServerInterceptor

CallServerInterceptor

这是链中的最后一个拦截器。 它对服务器进行网络呼叫

是不是感觉不想看了?头晕眼皮重想睡觉?

稳住 我们能赢!!

上面获取到一系列的变量之后,然后调用了

这个方法里面是这样的

这个就是组装了一个头然后请求过去,然后接着判断当前请求的方法和body是否合法,然后往下走,判断一下如果请求中有一个“Expect:100-continue”头,等待“HTTP / 1.1 100 Continue”响应, 平常也没有 ,然后往下走,判断responseBuilder 如果为空的话,调用httpCodec的createRequestBody,它里面的经过重重调用之后,最后是调用的这个方法

从CallServerInterceptor 调用过来的这个方法的countBytes是false, 用的是sink的buff 这个sink的buff现在就是socket的流操作 ,把请求提写入到socket里面,完成请求,具体的整个sokcet请求的流程我会在教程里讲,这里就不多叙述。

接着上面的说,请求完之后 responseBuilder 是通过httpcodec的readResponseHeaders来创建,里面有请求回来的请求码, 状态和头部,然后根据responseBuilder构架response,把当前的请求,握手,发送请求的时间,服务器返回的时间放到response里面,此处忽略101先,然后看到response又通过builder去放入返回的body,如果是20X的话就抛出异常,然后返回response。 此处又该往回走,在RealInterceptorChain 里面后半部分,处理了一下结尾,然后返回Response,然后RealCall里面的getResponseWithInterceptorChain()返回Response,然后在execute或者AsyncCall的execute里面返回Response,如果是AsuncCall的话返回到回调里,这个流程就完成了。

  • 发表于:
  • 原文链接http://kuaibao.qq.com/s/20180110B00UM400?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券