一、重试和重定向拦截器
RetryAndFollowUpInterceptor ,主要作用是重定向的判断,重试的判断。
本拦截器是整个责任链中的第一个,这意味着它会是首次接触到Request
与最后接收到Response
的角色,在这个拦截器中主要功能就是判断是否需要重试与重定向。
重试的前提是出现了RouteException
或者IOException
。一但在后续的拦截器执行过程中出现这两个异常,就会通过recover
方法进行判断是否进行连接重试。
重定向发生在重试的判定之后,一般服务器在返回3XX的错误码,并且会携带Location的响应头就会发生重定向的操作,如果不满足重试的条件,还需要进一步调用followUpRequest
根据Response
的响应码(当然,如果直接请求失败,Response
都不存在就会抛出异常)。followup
最大发生20次。
二、桥接拦截器
BridgeInterceptor,连接应用程序和服务器的桥梁,我们发出的请求将会经过它的处理才能发给服务器,比如设置请求内容长度,编码,gzip压缩,cookie等,获取响应后保存Cookie等操作。这个拦截器相对比较简单。
补全请求头:
请求头 | 说明 |
---|---|
Content-Type | 请求体类型,如:application/x-www-form-urlencoded |
Content-Length /Transfer-Encoding | 请求体解析方式 |
Host | 请求的主机站点 |
Connection: Keep-Alive | 保持长连接 |
Accept-Encoding: gzip | 接受响应支持gzip压缩 |
Cookie | cookie身份辨别 |
User-Agent | 请求的用户信息,如:操作系统、浏览器等 |
在补全了请求头后交给下一个拦截器处理,得到响应后,主要干两件事情:
1、保存cookie,在下次请求则会读取对应的数据设置进入请求头,默认的CookieJar
不提供实现
2、如果使用gzip返回的数据,则使用GzipSource
包装便于解析。
总结
桥接拦截器的执行逻辑主要就是以下几点
对用户构建的Request
进行添加或者删除相关头部信息,以转化成能够真正进行网络请求的Request
将符合网络请求规范的Request交给下一个拦截器处理,并获取Response
如果响应体经过了GZIP压缩,那就需要解压,再构建成用户可用的Response
并返回
三、缓存拦截器
CacheInterceptor,在发出请求前,判断是否命中缓存。如果命中则可以不请求,直接使用缓存的响应。 (只会存在Get请求的缓存)
步骤为:
1、从缓存中获得对应请求的响应缓存
2、创建CacheStrategy
,创建时会判断是否能够使用缓存,在CacheStrategy
中存在两个成员:networkRequest
与cacheResponse
。他们的组合如下:
networkRequest | cacheResponse | 说明 |
---|---|---|
Null | Not Null | 直接使用缓存 |
Not Null | Null | 向服务器发起请求 |
Null | Null | 直接gg,okhttp直接返回504 |
Not Null | Not Null | 发起请求,若得到响应为304(无修改),则更新缓存响应并返回 |
3、交给下一个责任链继续处理
4、后续工作,返回304则用缓存的响应;否则使用网络响应并缓存本次响应(只缓存Get请求的响应)
缓存策略见下图
缓存拦截器的工作说起来比较简单,但是具体的实现,需要处理的内容很多。在缓存拦截器中判断是否可以使用缓存,或是请求服务器都是通过CacheStrategy
判断。
四、连接拦截器
ConnectInterceptor
,打开与目标服务器的连接,并执行下一个拦截器。
拦截池,保存了一些socket连接,供请求复用。针对同一域名的请求可以复用相同的socket连接。拦截池最多保存5个连接,每个连接最多保存5分钟。
如果是https连接,需要先发送一个connect请求,待服务器返回200 后,再讲请求包装成SSLSocket就可以发送请求了。
五、请求服务拦截器
CallServerInterceptor,利用HttpCodec
发出请求到服务器并且解析生成Response
OkHttp总结
整个OkHttp功能的实现就在这五个默认的拦截器中,所以先理解拦截器模式的工作机制是先决条件。这五个拦截器分别为: 重试拦截器、桥接拦截器、缓存拦截器、连接拦截器、请求服务拦截器。每一个拦截器负责的工作不一样,就好像工厂流水线,最终经过这五道工序,就完成了最终的产品。
但是与流水线不同的是,OkHttp中的拦截器每次发起请求都会在交给下一个拦截器之前干一些事情,在获得了结果之后又干一些事情。整个过程在请求向是顺序的,而响应向则是逆序。
当用户发起一个请求后,会由任务分发起Dispatcher
将请求包装并交给重试拦截器处理。
1、重试拦截器在交出(交给下一个拦截器)之前,负责判断用户是否取消了请求;在获得了结果之后,会根据响应码判断是否需要重定向,如果满足条件那么就会重启执行所有拦截器。
2、桥接拦截器在交出之前,负责将HTTP协议必备的请求头加入其中(如:Host)并添加一些默认的行为(如:GZIP压缩);在获得了结果后,调用保存cookie接口并解析GZIP数据。
3、缓存拦截器顾名思义,交出之前读取并判断是否使用缓存;获得结果后判断是否缓存。
4、连接拦截器在交出之前,负责找到或者新建一个连接,并获得对应的socket流;在获得结果后不进行额外的处理。
5、请求服务器拦截器进行真正的与服务器的通信,向服务器发送数据,解析读取的响应数据。
在经过了这一系列的流程后,就完成了一次HTTP请求!