okhttp 责任链拦截器

拦截器
  • 用户自定义的拦截器
    • 应用拦截器 在所有拦截器的前面
    • 网络拦截器 在 RetryAndFollowUpInterceptor、BridgeInterceptor、CacheInterceptor、ConnectInterceptor拦截器的后面,CallServerInterceptor拦截器的后面

1、 RetryAndFollowUpInterceptor

连接失败后进行重试、对请求结果跟进后进行重定向

  • 如果通过 RouteException
    • 通过单个路由出现了多次链接都失败以后出现此异常
    • 根据 recover 判断是否需要重连
  • 如果没有添加应用拦截器,那么RetryAndFollowUpInterceptor就是第一个拦截器,主要功能是判断是否需要重试和重定向。
    如果请求阶段发生了IOException,就会通过recover方法判断是进行连接重试。
    重定向发生在重试的判定之后,如果不满足重试的条件,还需要进一步调用followUpRequest根据Response 的响应码(
    当然,如果直接请求失败,Response都不存在就会抛出异常)判断是否重定向;followup最大发生次数20次。

2、 BridgeInterceptor

BridgeInterceptor,连接应用程序和服务器的桥梁,我们发出的请求会经过它的处理才能发给服务器,
比如设置请求内容的长度,编码,gzip压缩,cookie等;获取响应后保存cookie、解压等操作。
相对比较简单。

  • 对用户构建的Request进行添加或者删除相关头部信息,以转化成能够真正进行网络请求的Request。
  • 将符合网络请求规范的Request交给下一个拦截器处理,并获取Response。
  • 如果响应体经过了gzip压缩,那就需要解压,再构建成用户可用的Response并返回。

首先,chain.proceed()执行前,对请求头进行补全,补全请求头如下:

请求头 说明
Content-Type 请求体类型,如:application/x-www-form-urlencoded
Content-Length/Transfer-Encoding 请求体解析方式
Host 请求的主机站点
Connection: Keep-Alive 保持长连接
Accept-Encoding: gzip 接受响应支持gzip压缩
Cookie cookie身份辨别
User-Agent 请求的用户信息,如:操作系统、浏览器等

先把响应header中的cookie存入cookieJar(如果有),在下次请求则会读取对应的数据设置进入请求头,默认的CookieJar不提供实现,需要我们在初始化OkhttpClient时配置我们自己的cookieJar。
如果使用gzip返回的数据,则使用GzipSource包装便于解析

3、 CacheInterceptor

CacheInterceptor,在发出请求前,先判断是否命中缓存,如果命中则可以不请求,直接使用缓存的响应(默认只会对Get请求进行缓存);如果未命中则进行网络请求,并将结果缓存,等待下次请求被命中。

大概梳理一下步骤:

  • 从缓存中获取对应请求的响应缓存
  • 创建CacheStrategy,创建时会判断是否能够使用缓存,在CacheStrategy中有两个成员:networkRequest和cacheResponse。他们有如下组合进行判断:
networkRequest cacheResponse 说明
Null Null 网络请求、缓存 都不能用,okhttp直接返回504
Null Not Null 直接使用缓存
Not Null Null 向服务器发起请求
Not Null Not Null 向服务器发起请求,若得到响应码为304(无修改),则更新缓存响应并返回
  • 交给下一个责任链继续处理
  • 后续工作,返回304则用缓存的响应;否则使用网络响应并缓存本次响应(只缓存Get请求的响应)
  • 缓存拦截器中判断使用缓存或者请求服务器都是通过CacheStrategy判断。分析CacheStrategy前我们先来了解下Http的缓存机制,以便更好的理解:
okhttp_cache.png
okhttp_cache_2.png

4、 ConnectInterceptor

这个拦截器主要的作用就是负责从连接池获取健康的连接(判断连接的 Socket 传输通道是否可用),如果在连接池中没有找到符合复用的连接(除了主机地址之外的信息必须要全部匹配,例如 DNS、代理、协议、证书),那么就会使用路由再找一遍(路由的结构是一个代理服务器的地址 + DNS 中的一个 IP 地址),如果还是没有,那么会直接创建一个新的连接对象并进行三次握手,再将这个新的连接对象添加到连接池中,最后将可复用的连接返回回去

4、 CallServerInterceptor

CalllServerInterceptor是最后一个拦截器了,前面的拦截器已经完成了socket连接和tls连接,那么这一步就是传输http的头部和body数据了。

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容