OkHttp源码解析(二)五大拦截器

一.五大拦截器总体介绍

在前面分发器的介绍中,可以看到通过getResponseWithInterceptorChain这一个方法,就可以获得响应。这个方法里面是这样的
在这里插入图片描述
除了两个用户可以自己添加的拦截器之外,剩下的五个是默认的拦截器。他们之间是用责任链模式连接在一起

1.责任链模式

概念:责任链上的处理者负责处理请求,客户只需要将请求发送到责任链即可,无须关心请求的处理细节和请求的传递,所以职 责链将请求的发送者和请求的处理者解耦了

比如点个外卖,它的流程是这样的
在这里插入图片描述
我不必关心内部是具体怎么给我做的饭,美团外卖只管提供平台和送餐,饭店只管接单和派单,厨师只管接收菜和做菜。他们之间是一个U型结构,类似于Android的事件分发。

这五大拦截器之间也是责任链模式,具体可用一张图表示
在这里插入图片描述

2.五大拦截器的责任链模式抽取

我们建立这几个类和接口
在这里插入图片描述
上面五个是拦截器,Chain是链条类,负责串联这几个拦截器,Interceptor是接口,MyClass是程序入口。我们进入MyClass
在这里插入图片描述
这里首先创建了五个拦截器,然后通过Chain将五大拦截器串起来,index设为0,然后调用chainprocessd方法
在这里插入图片描述
看下第一个拦截器的intercept方法
在这里插入图片描述
然后调用chain(索引值从1开始,也就是从第二个拦截器开始)的processd方法。再以此类推,直到调用了第五个拦截器的intercept方法
在这里插入图片描述
然后依次返回,一直到第一个。
也就是说先调用chainprocessd方法,找到第一个拦截器,然后调用其intercept方法,然后再调用chainprocessd方法,找到第二个拦截器,然后调用其intercept方法,然后再调用chainprocessd方法,以此类推,直到找到第五个拦截器,调用其intercept方法,执行完了之后将结果依次返回到第一个拦截器。

3.各个拦截器的功能

重试和重定向拦截器
它在交出(交给下一个拦截器)之前,负责判断是否需要重新发起请求(重试);在获得了结果之后 ,会根据响应码判断是否需要重定向,如果满足条件那么就会重启执行所有拦截器。 (它是最早接收Request的,也是最晚接收Response的)
在这里插入图片描述
返回码是3xx的,就需要重定向了
桥接拦截器
在交出之前,负责将HTTP协议必备的请求头,加入其中(如:Host)并添加一些默认的行为(如:GZIP压缩);在获得了结果后,调用保存cookie接口并解析GZIP数据。
缓存拦截器
顾名思义,交出之前读取并判断是否使用缓存;获得结果后判断是否缓存。
连接拦截器
在交出之前,负责找到或者新建一个连接,并获得对应的socket流;在获得结果后不进行额外的处理。
请求服务器拦截器
进行真正的与服务器的通信,向服务器发送数据,解析读取的响应数据。

二.RetryAndFollowUpInterceptor

重试和重定向拦截器。它对Request没有做什么特殊的操作,而是把重心放在了Response上面。直接看源码
在这里插入图片描述
可以看到它直接把request传进去的。
这里有几个值得注意的点
①整个重试和重定向过程是在一个while循环里面
②通过try catch来实现重试,具体是catch里面的continue
在这里插入图片描述
也就是请求异常的时候,会进入catch里面,如果recover方法返回true,那就可以重试。下面就进入这个recover方法看一看

1.recover判断是否可以重试

在这里插入图片描述
不允许重试的情况有四种
①通过其建造者模式,创建OkHttpClient的时候,给他配置了不可重试。
在其Builder类里面,有这么一个方法,传入false,就设置了不可重试
在这里插入图片描述
当然,如果不设置,默认情况下,是true,即可重试
在这里插入图片描述
②对某一次请求设置不可重试。(用的少)
上面那种情况是全局的,这个是某一次的。具体方法是自定义一个请求体,然后让其实现标识接口UnrepeatableRequestBody
如图
在这里插入图片描述
isRecoverable方法返回false,不可重试
我们看下isRecoverable方法
在这里插入图片描述
如果是协议异常,就不可重试
比如在CallServerInterceptor的这里
在这里插入图片描述
204和205的意思是响应体中没有内容,而后面的contentLength大于0又说响应体中有内容,所以协议冲突了,抛出异常。一般是服务器的原因
在这里插入图片描述
如果是请求时间过长,那么可以重试(比如发生网络波动了)
如果是证书不正确,或者不匹配,都不能重试
④有没有更多的路由
比如有A代理和B代理,A代理不行,可以试试B代理,两者都不行,就是没有路由了,就不能重试了

所以,总结下重试的逻辑
如果OkHttpClient允许重试,isRecoverable方法返回true,且拥有更多的路线,才能进行重试。如图
在这里插入图片描述
所以重试的条件是很苛刻的。

2.重定向

假如成功获得响应,那么走出try catch,走下面,如图
在这里插入图片描述
如果返回的响应码是需要重定向的响应码,如301,302,则followUpRequest方法会解析响应头里面的location字段,并将location里面的url组建成一个新的request,返回,也就是让followUp接收。如果followUpnull,就是没有location,那就是不需要重定向。当然重定向的次数有限制,最多为20次,即MAX_FOLLOW_UPS

除了30x的响应码,需要重定向之外,其他的有一些响应码需要特殊处理。如图
在这里插入图片描述

三.BridgeInterceptor

桥接拦截器,
它对Request的操作,就是帮我们添加各种请求头。如图

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值