这个拦截器就是用于处理这些情况,我们就叫它 缓存拦截器 吧 。
- 拦截器6: 自定义拦截器
这下好像齐了,至于之前说的7个拦截器还有1个,留个悬念最后再说 。
最后再给他们排个序吧:
- 1、自定义拦截器的公共参数处理 。
- 2、封装拦截器封装请求报文
- 3、缓存拦截器的缓存复用 。
- 4、连接拦截器建立TCP连接 。
- 5、IO拦截器的数据写入 。
- 6、IO拦截器的数据读取 。
- 7、缓存拦截器保存响应数据缓存 。
- 8、封装拦截器分析响应报文
- 9、重试和重定向拦截器处理重试和重定向情况 。
- 10、自定义拦截器统一处理响应数据 。

文章插图
所以,拦截器的顺序也基本固定了:
- 1、自定义拦截器
- 2、重试和重定向拦截器
- 3、封装拦截器
- 4、缓存拦截器
- 5、连接拦截器
- 6、IO拦截器
自定义拦截器在请求之前,我们一般创建自己的自定义拦截器,用于添加一些接口公共参数,比如把 token 加到Header中 。
class MyInterceptor() : Interceptor {override fun intercept(chain: Interceptor.Chain): Response {var request = chain.request()request = request.newBuilder().addHeader("token", "token").url(url).build()return chain.proceed(request)}要注意的是,别忘了调用 chain.proceed ,否则这条链就无法继续下去了 。在获取响应之后,我们一般用拦截器进行结果打印,比如常用的 HttpLoggingInterceptor 。
addInterceptor(HttpLoggingInterceptor().Apply {level = HttpLoggingInterceptor.Level.BODY})重试和重定向拦截器(RetryAndFollowUpInterceptor)为了方便理解,我对源码进行了修剪:scissors::class RetryAndFollowUpInterceptor(private val client: OkHttpClient) : Interceptor {@Throws(IOException::class)override fun intercept(chain: Interceptor.Chain): Response {while (true) {try {try {response = realChain.proceed(request)} catch (e: RouteException) {//路由错误continue} catch (e: IOException) {// 请求错误continue}//获取响应码判断是否需要重定向val followUp = followUpRequest(response, exchange)if (followUp == null) {//没有重定向return response}//赋予重定向请求,再次进入下一次循环request = followUp}}}}这样代码就很清晰了,重试和重定向的处理都是需要重新请求,所以这里用到了while循环 。realChain.proceed重定向response封装拦截器(BridgeInterceptor)class BridgeInterceptor(private val cookieJar: CookieJar) : Interceptor {@Throws(IOException::class)override fun intercept(chain: Interceptor.Chain): Response {//添加头部信息requestBuilder.header("Content-Type", contentType.toString())requestBuilder.header("Host", userRequest.url.toHostHeader())requestBuilder.header("Connection", "Keep-Alive")requestBuilder.header("Accept-Encoding", "gzip")requestBuilder.header("Cookie", cookieHeader(cookies))requestBuilder.header("User-Agent", userAgent)val networkResponse = chain.proceed(requestBuilder.build())//解压val responseBuilder = networkResponse.newBuilder().request(userRequest)if (transparentGzip &&"gzip".equals(networkResponse.header("Content-Encoding"), ignoreCase = true) &&networkResponse.promisesBody()) {val responseBody = networkResponse.bodyif (responseBody != null) {val gzipSource = GzipSource(responseBody.source())responseBuilder.body(RealResponseBody(contentType, -1L, gzipSource.buffer()))}}return responseBuilder.build()}请求前的代码很简单,就是添加了一些必要的头部信息,包括 Content-Type、Host、Cookie 等等,封装成一个完整的请求报文,然后交给下一个拦截器 。而获取响应后的代码就有点不是很明白了, gzip 是啥? GzipSource 又是什么类?
gzip压缩是基于deflate中的算法进行压缩的,gzip会产生自己的数据格式,gzip压缩对于所需要压缩的文件,首先使用LZ77算法进行压缩,再对得到的结果进行huffman编码,根据实际情况判断是要用动态huffman编码还是静态huffman编码,最后生成相应的gz压缩文件 。
推荐阅读
- 从零开始怎样练太极拳基本功
- 调养视网膜脱落从太极拳养身开始
- 招聘|从一线到三四线城市,中超赛区接连遇冷,陈戌源担心事情还是发生
- 五亿年后的地球 从宇宙诞生到地球灭亡
- nasa空间站直播 nasa国际空间站直播
- 路由器|坐等换路由!Wi-Fi 7加速到来:网络体验完美取代Wi-Fi 6
- 十大潮州美食推荐
- 紫沙茶罐图片,图片来源于网络
- K8S 的网络架构弄清楚了吗?
- 爱因斯坦说蜜蜂在地球上消失 爱因斯坦说蜜蜂如果从世界上消失会怎么样
