[JAVA] JavaOkHttp框架源码超详细解析

2706 0
王子 2022-11-8 17:22:32 | 显示全部楼层 |阅读模式
目录

    一、自己的理解的OkHttp二、OkHttp的使用方法三、基本对象介绍
      1.OkHttpClient2.request3.Call4.RealCall5.AsyncCall6.Dispatcher
    四、流程分析
      1.同步请求2.异步请求3.获取Response
    五、Interceptor六、RealInterceptorChain七、拦截器
      1.client.interceptors2.RetryAndFollowUpInterceptor3.BridgeInterceptor4.CacheInterceptor5.ConnectInterceptor6.client.networkInterceptors7.CallServerInterceptor



一、自己的理解的OkHttp

我理解的http的本质就是基于socket连接,把要传输的数据按照http协议的格式去封装后,传输在网络中,以此来实现的网络通信。
而OkHttp协议就是帮助我们,把我们把要传输的数据请求,按照http协议的格式,传输在Socket上,当然还有很多优化管理这些请求和连接的方法,例如:对于这些请求的管理:最多同时进行64个请求,同域名的最多同时进行5个请求。还有Socket连接池的管理。

二、OkHttp的使用方法

1.创建一个client,构建一个request
  1. OkHttpClient client = new OkHttpClient();
  2.     Request request = new Request.Builder()
  3.       .url("https://www.baidu.com/")
  4.       .build();
复制代码
2.同步请求
  1. Response response = client.newCall(request).execute();
复制代码
3.异步请求
  1.     client.newCall(request).enqueue(new Callback() {
  2.       @Override
  3.       public void onFailure(@NotNull Call call, @NotNull IOException e) {
  4.       //todo handle request failed
  5.       }
  6.       @Override
  7.       public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
  8.           //todo handle Response
  9.       }
  10.     });
复制代码
三、基本对象介绍


1.OkHttpClient

一个请求的配置类,采用了建造者模式,方便用户配置一些请求参数,如配置callTimeout,cookie,interceptor等等。
  1. open class OkHttpClient internal constructor(
  2.   builder: Builder
  3. ) : Cloneable, Call.Factory, WebSocket.Factory {
  4.   constructor() : this(Builder())
  5.   class Builder constructor() {
  6.     //调度器
  7.     internal var dispatcher: Dispatcher = Dispatcher()
  8.     //连接池
  9.     internal var connectionPool: ConnectionPool = ConnectionPool()
  10.     //整体流程拦截器
  11.     internal val interceptors: MutableList<Interceptor> = mutableListOf()
  12.     //网络流程拦截器
  13.     internal val networkInterceptors: MutableList<Interceptor> = mutableListOf()
  14.     //流程监听器
  15.     internal var eventListenerFactory: EventListener.Factory = EventListener.NONE.asFactory()
  16.     //连接失败时是否重连
  17.     internal var retryOnConnectionFailure = true
  18.     //服务器认证设置
  19.     internal var authenticator: Authenticator = Authenticator.NONE
  20.     //是否重定向
  21.     internal var followRedirects = true
  22.     //是否从HTTP重定向到HTTPS
  23.     internal var followSslRedirects = true
  24.     //cookie设置
  25.     internal var cookieJar: CookieJar = CookieJar.NO_COOKIES
  26.     //缓存设置
  27.     internal var cache: Cache? = null
  28.     //DNS设置
  29.     internal var dns: Dns = Dns.SYSTEM
  30.     //代理设置
  31.     internal var proxy: Proxy? = null
  32.     //代理选择器设置
  33.     internal var proxySelector: ProxySelector? = null
  34.     //代理服务器认证设置
  35.     internal var proxyAuthenticator: Authenticator = Authenticator.NONE
  36.     //socket配置
  37.     internal var socketFactory: SocketFactory = SocketFactory.getDefault()
  38.     //https socket配置
  39.     internal var sslSocketFactoryOrNull: SSLSocketFactory? = null
  40.     internal var x509TrustManagerOrNull: X509TrustManager? = null
  41.     internal var connectionSpecs: List<ConnectionSpec> = DEFAULT_CONNECTION_SPECS
  42.     //协议
  43.     internal var protocols: List<Protocol> = DEFAULT_PROTOCOLS
  44.     //域名校验
  45.     internal var hostnameVerifier: HostnameVerifier = OkHostnameVerifier
  46.     internal var certificatePinner: CertificatePinner = CertificatePinner.DEFAULT
  47.     internal var certificateChainCleaner: CertificateChainCleaner? = null
  48.     //请求超时
  49.     internal var callTimeout = 0
  50.     //连接超时
  51.     internal var connectTimeout = 10_000
  52.     //读取超时
  53.     internal var readTimeout = 10_000
  54.     //写入超时
  55.     internal var writeTimeout = 10_000
  56.     internal var pingInterval = 0
  57.     internal var minWebSocketMessageToCompress = RealWebSocket.DEFAULT_MINIMUM_DEFLATE_SIZE
  58.     internal var routeDatabase: RouteDatabase? = null
  59. ···省略代码···
复制代码
2.request

同样是请求参数的配置类,也同样采用了建造者模式,但相比于OkHttpClient,Request就十分简单了,只有四个参数,分别是请求URL、请求方法、请求头、请求体。
  1. class Request internal constructor(
  2.   @get:JvmName("url") val url: HttpUrl,
  3.   @get:JvmName("method") val method: String,
  4.   @get:JvmName("headers") val headers: Headers,
  5.   @get:JvmName("body") val body: RequestBody?,
  6.   internal val tags: Map<Class<*>, Any>
  7. ) {
  8.   open class Builder {
  9.     //请求的URL
  10.     internal var url: HttpUrl? = null
  11.     //请求方法,如:GET、POST..
  12.     internal var method: String
  13.     //请求头
  14.     internal var headers: Headers.Builder
  15.     //请求体
  16.     internal var body: RequestBody? = null
  17.   ···省略代码···
复制代码
3.Call

请求调用接口,表示这个请求已经准备好可以执行,也可以取消,只能执行一次。
  1. interface Call : Cloneable {
  2.   /** 返回发起此调用的原始请求 */
  3.   fun request(): Request
  4.   /**
  5.    * 同步请求,立即执行。
  6.    *
  7.    * 抛出两种异常:
  8.    * 1. 请求失败抛出IOException;
  9.    * 2. 如果在执行过一回的前提下再次执行抛出IllegalStateException;*/
  10.   @Throws(IOException::class)
  11.   fun execute(): Response
  12.   /**
  13.    * 异步请求,将请求安排在将来的某个时间点执行。
  14.    * 如果在执行过一回的前提下再次执行抛出IllegalStateException */
  15.   fun enqueue(responseCallback: Callback)
  16.   /** 取消请求。已经完成的请求不能被取消 */
  17.   fun cancel()
  18.   /** 是否已被执行  */
  19.   fun isExecuted(): Boolean
  20.   /** 是否被取消   */
  21.   fun isCanceled(): Boolean
  22.   /** 一个完整Call请求流程的超时时间配置,默认选自[OkHttpClient.Builder.callTimeout] */
  23.   fun timeout(): Timeout
  24.   /** 克隆这个call,创建一个新的相同的Call */
  25.   public override fun clone(): Call
  26.   /** 利用工厂模式来让 OkHttpClient 来创建 Call对象 */
  27.   fun interface Factory {
  28.     fun newCall(request: Request): Call
  29.   }
  30. }
复制代码
4.RealCall
  1. OkHttpClient.kt
  2. override fun newCall(request: Request): Call = RealCall(this, request, forWebSocket = false)
复制代码
RealCall是Call接口的具体实现类,是应用端与网络层的连接桥,展示应用端原始的请求与连接数据,以及网络层返回的response及其它数据流。 通过使用方法也可知,创建RealCall对象后,就要调用同步或异步请求方法,所以它里面还包含同步请求 execute()与异步请求 enqueue()方法。(后面具体展开分析)

5.AsyncCall

异步请求调用,是RealCall的一个内部类,就是一个Runnable,被dispatcher调度器中的线程池所执行。
  1. inner class AsyncCall(
  2.     //用户传入的响应回调方法
  3.     private val responseCallback: Callback
  4.   ) : Runnable {
  5.     //同一个域名的请求次数,volatile + AtomicInteger 保证在多线程下及时可见性与原子性
  6.     @Volatile var callsPerHost = AtomicInteger(0)
  7.       private set
  8.     fun reuseCallsPerHostFrom(other: AsyncCall) {
  9.       this.callsPerHost = other.callsPerHost
  10.     }
  11. ···省略代码···
  12.     fun executeOn(executorService: ExecutorService) {
  13.       client.dispatcher.assertThreadDoesntHoldLock()
  14.       var success = false
  15.       try {
  16.         //调用线程池执行
  17.         executorService.execute(this)
  18.         success = true
  19.       } catch (e: RejectedExecutionException) {
  20.         val ioException = InterruptedIOException("executor rejected")
  21.         ioException.initCause(e)
  22.         noMoreExchanges(ioException)
  23.         //请求失败,调用 Callback.onFailure() 方法
  24.         responseCallback.onFailure(this@RealCall, ioException)
  25.       } finally {
  26.         if (!success) {
  27.           //请求失败,调用调度器finish方法
  28.           client.dispatcher.finished(this) // This call is no longer running!
  29.         }
  30.       }
  31.     }
  32.     override fun run() {
  33.       threadName("OkHttp ${redactedUrl()}") {
  34.         var signalledCallback = false
  35.         timeout.enter()
  36.         try {
  37.           //请求成功,获取到服务器返回的response
  38.           val response = getResponseWithInterceptorChain()
  39.           signalledCallback = true
  40.           //调用 Callback.onResponse() 方法,将 response 传递出去
  41.           responseCallback.onResponse(this@RealCall, response)
  42.         } catch (e: IOException) {
  43.           if (signalledCallback) {
  44.             // Do not signal the callback twice!
  45.             Platform.get().log("Callback failure for ${toLoggableString()}", Platform.INFO, e)
  46.           } else {
  47.             //请求失败,调用 Callback.onFailure() 方法
  48.             responseCallback.onFailure(this@RealCall, e)
  49.           }
  50.         } catch (t: Throwable) {
  51.           //请求出现异常,调用cancel方法来取消请求
  52.           cancel()
  53.           if (!signalledCallback) {
  54.             val canceledException = IOException("canceled due to $t")
  55.             canceledException.addSuppressed(t)
  56.             //请求失败,调用 Callback.onFailure() 方法
  57.             responseCallback.onFailure(this@RealCall, canceledException)
  58.           }
  59.           throw t
  60.         } finally {
  61.           //请求结束,调用调度器finish方法
  62.           client.dispatcher.finished(this)
  63.         }
  64.       }
  65.     }
  66.   }
复制代码
6.Dispatcher

调度器,用来调度Call对象,同时包含线程池与异步请求队列,用来存放与执行AsyncCall对象。
  1. class Dispatcher constructor() {
  2.   @get:Synchronized
  3.   @get:JvmName("executorService") val executorService: ExecutorService
  4.     get() {
  5.       if (executorServiceOrNull == null) {
  6.         //创建一个缓存线程池,来处理请求调用,这个线程池的核心线程数是0,等待队列的长度也是0,意味着
  7.         //线程池会直接创建新的线程去处理请求
  8.         executorServiceOrNull = ThreadPoolExecutor(0, Int.MAX_VALUE, 60, TimeUnit.SECONDS,
  9.             SynchronousQueue(), threadFactory("$okHttpName Dispatcher", false))
  10.       }
  11.       return executorServiceOrNull!!
  12.     }
  13.   /** 已准备好的异步请求队列 */
  14.   @get:Synchronized
  15.   private val readyAsyncCalls = ArrayDeque<AsyncCall>()
  16.   /** 正在运行的异步请求队列, 包含取消但是还未finish的AsyncCall */
  17.   private val runningAsyncCalls = ArrayDeque<AsyncCall>()
  18.   /** 正在运行的同步请求队列, 包含取消但是还未finish的RealCall */
  19.   private val runningSyncCalls = ArrayDeque<RealCall>()
  20. ···省略代码···
  21. }
复制代码
四、流程分析


1.同步请求
  1. client.newCall(request).execute();
复制代码
newCall方法就是创建一个RealCall对象,然后执行其execute()方法。
  1.   RealCall.kt
  2.   override fun execute(): Response {
  3.     //CAS判断是否已经被执行了, 确保只能执行一次,如果已经执行过,则抛出异常
  4.     check(executed.compareAndSet(false, true)) { "Already Executed" }
  5.     //请求超时开始计时
  6.     timeout.enter()
  7.     //开启请求监听
  8.     callStart()
  9.     try {
  10.       //调用调度器中的 executed() 方法,调度器只是将 call 加入到了runningSyncCalls队列中
  11.       client.dispatcher.executed(this)
  12.       //调用getResponseWithInterceptorChain 方法拿到 response
  13.       return getResponseWithInterceptorChain()
  14.     } finally {
  15.       //执行完毕,调度器将该 call 从 runningSyncCalls队列中移除
  16.       client.dispatcher.finished(this)
  17.     }
  18.   }
  19.   Dispatcher.kt
  20.   @Synchronized internal fun executed(call: RealCall) {
  21.     runningSyncCalls.add(call)
  22.   }
复制代码
调用调度器executed方法,就是将当前的RealCall对象加入到runningSyncCalls队列中,然后调用getResponseWithInterceptorChain方法拿到response。

2.异步请求
  1.   RealCall.kt
  2.   override fun enqueue(responseCallback: Callback) {
  3.     //CAS判断是否已经被执行了, 确保只能执行一次,如果已经执行过,则抛出异常
  4.     check(executed.compareAndSet(false, true)) { "Already Executed" }
  5.     //开启请求监听
  6.     callStart()
  7.     //新建一个AsyncCall对象,通过调度器enqueue方法加入到readyAsyncCalls队列中
  8.     client.dispatcher.enqueue(AsyncCall(responseCallback))
  9.   }
复制代码
然后调用调度器的enqueue方法
  1.   Dispatcher.kt
  2.   internal fun enqueue(call: AsyncCall) {
  3.     //加锁,保证线程安全
  4.     synchronized(this) {
  5.       //将该请求调用加入到 readyAsyncCalls 队列中
  6.       readyAsyncCalls.add(call)
  7.       // Mutate the AsyncCall so that it shares the AtomicInteger of an existing running call to
  8.       // the same host.
  9.       if (!call.call.forWebSocket) {
  10.         //通过域名来查找有没有相同域名的请求,有则复用。
  11.         val existingCall = findExistingCallWithHost(call.host)
  12.         if (existingCall != null) call.reuseCallsPerHostFrom(existingCall)
  13.       }
  14.     }
  15.     //执行请求
  16.     promoteAndExecute()
  17.   }
  18.   private fun promoteAndExecute(): Boolean {
  19.     this.assertThreadDoesntHoldLock()
  20.     val executableCalls = mutableListOf<AsyncCall>()
  21.     //判断是否有请求正在执行
  22.     val isRunning: Boolean
  23.     //加锁,保证线程安全
  24.     synchronized(this) {
  25.       //遍历 readyAsyncCalls 队列
  26.       val i = readyAsyncCalls.iterator()
  27.       while (i.hasNext()) {
  28.         val asyncCall = i.next()
  29.         //runningAsyncCalls 的数量不能大于最大并发请求数 64
  30.         if (runningAsyncCalls.size >= this.maxRequests) break // Max capacity.
  31.         //同域名最大请求数5,同一个域名最多允许5条线程同时执行请求
  32.         if (asyncCall.callsPerHost.get() >= this.maxRequestsPerHost) continue // Host max capacity.
  33.         //从 readyAsyncCalls 队列中移除,并加入到 executableCalls 及 runningAsyncCalls 队列中
  34.         i.remove()
  35.         asyncCall.callsPerHost.incrementAndGet()
  36.         executableCalls.add(asyncCall)
  37.         runningAsyncCalls.add(asyncCall)
  38.       }
  39.       //通过运行队列中的请求数量来判断是否有请求正在执行
  40.       isRunning = runningCallsCount() > 0
  41.     }
  42.     //遍历可执行队列,调用线程池来执行AsyncCall
  43.     for (i in 0 until executableCalls.size) {
  44.       val asyncCall = executableCalls[i]
  45.       asyncCall.executeOn(executorService)
  46.     }
  47.     return isRunning
  48.   }
复制代码
调度器的enqueue方法就是将AsyncCall加入到readyAsyncCalls队列中,然后调用promoteAndExecute方法来执行请求,promoteAndExecute方法做的其实就是遍历readyAsyncCalls队列,然后将符合条件的请求用线程池执行,也就是会执行AsyncCall.run()方法。
AsyncCall 方法的具体代码看上面的这边就不在此展示了,简单来说就是调用getResponseWithInterceptorChain方法拿到response,然后通过Callback.onResponse方法传递出去。反之,如果请求失败,捕获了异常,就通过Callback.onFailure将异常信息传递出去。 最终,请求结束,调用调度器finish方法。
  1.   Dispatcher.kt
  2.   /** 异步请求调用结束方法 */
  3.   internal fun finished(call: AsyncCall) {
  4.     call.callsPerHost.decrementAndGet()
  5.     finished(runningAsyncCalls, call)
  6.   }
  7.   /** 同步请求调用结束方法 */
  8.   internal fun finished(call: RealCall) {
  9.     finished(runningSyncCalls, call)
  10.   }
  11.   private fun <T> finished(calls: Deque<T>, call: T) {
  12.     val idleCallback: Runnable?
  13.     synchronized(this) {
  14.       //将当前请求调用从 正在运行队列 中移除
  15.       if (!calls.remove(call)) throw AssertionError("Call wasn't in-flight!")
  16.       idleCallback = this.idleCallback
  17.     }
  18.     //继续执行剩余请求,将call从readyAsyncCalls中取出加入到runningAsyncCalls,然后执行
  19.     val isRunning = promoteAndExecute()
  20.     if (!isRunning && idleCallback != null) {
  21.       //如果执行完了所有请求,处于闲置状态,调用闲置回调方法
  22.       idleCallback.run()
  23.     }
  24.   }
复制代码
请求结束,异步请求,把当前同域名的计数减一,然后后面和同步一样,都是把请求从正在执行的队列中移除,然后继续执行剩余请求。

3.获取Response

接着就是看看getResponseWithInterceptorChain方法是如何拿到response的。
  1.   internal fun getResponseWithInterceptorChain(): Response {
  2.     //拦截器列表
  3.     val interceptors = mutableListOf<Interceptor>()
  4.     interceptors += client.interceptors
  5.     interceptors += RetryAndFollowUpInterceptor(client)
  6.     interceptors += BridgeInterceptor(client.cookieJar)
  7.     interceptors += CacheInterceptor(client.cache)
  8.     interceptors += ConnectInterceptor
  9.     if (!forWebSocket) {
  10.       interceptors += client.networkInterceptors
  11.     }
  12.     interceptors += CallServerInterceptor(forWebSocket)
  13.     //构建拦截器责任链
  14.     val chain = RealInterceptorChain(
  15.         call = this,
  16.         interceptors = interceptors,
  17.         index = 0,
  18.         exchange = null,
  19.         request = originalRequest,
  20.         connectTimeoutMillis = client.connectTimeoutMillis,
  21.         readTimeoutMillis = client.readTimeoutMillis,
  22.         writeTimeoutMillis = client.writeTimeoutMillis
  23.     )
  24.     //如果call请求完成,那就意味着交互完成了,没有更多的东西来交换了
  25.     var calledNoMoreExchanges = false
  26.     try {
  27.       //执行拦截器责任链来获取 response
  28.       val response = chain.proceed(originalRequest)
  29.       //如果被取消,关闭响应,抛出异常
  30.       if (isCanceled()) {
  31.         response.closeQuietly()
  32.         throw IOException("Canceled")
  33.       }
  34.       return response
  35.     } catch (e: IOException) {
  36.       calledNoMoreExchanges = true
  37.       throw noMoreExchanges(e) as Throwable
  38.     } finally {
  39.       if (!calledNoMoreExchanges) {
  40.         noMoreExchanges(null)
  41.       }
  42.     }
  43.   }
复制代码
简单概括一下:这里采用了责任链设计模式,通过拦截器构建了以RealInterceptorChain责任链,然后执行proceed方法来得到response。
那么,这又涉及拦截器是什么?拦截器责任链又是什么?

五、Interceptor

只声明了一个拦截器方法,在子类中具体实现,还包含一个Chain接口,核心方法是proceed(request)处理请求来获取response。
  1. fun interface Interceptor {
  2.   /** 拦截方法 */
  3.   @Throws(IOException::class)
  4.   fun intercept(chain: Chain): Response
  5.   interface Chain {
  6.     /** 原始请求数据 */
  7.     fun request(): Request
  8.     /** 核心方法,处理请求,获取response */
  9.     @Throws(IOException::class)
  10.     fun proceed(request: Request): Response
  11.     fun connection(): Connection?
  12.     fun call(): Call
  13.     fun connectTimeoutMillis(): Int
  14.     fun withConnectTimeout(timeout: Int, unit: TimeUnit): Chain
  15.     fun readTimeoutMillis(): Int
  16.     fun withReadTimeout(timeout: Int, unit: TimeUnit): Chain
  17.     fun writeTimeoutMillis(): Int
  18.     fun withWriteTimeout(timeout: Int, unit: TimeUnit): Chain
  19.   }
  20. }
复制代码
六、RealInterceptorChain

拦截器链就是实现Interceptor.Chain接口,重点就是复写的proceed方法。
  1. class RealInterceptorChain(
  2.   internal val call: RealCall,
  3.   private val interceptors: List<Interceptor>,
  4.   private val index: Int,
  5.   internal val exchange: Exchange?,
  6.   internal val request: Request,
  7.   internal val connectTimeoutMillis: Int,
  8.   internal val readTimeoutMillis: Int,
  9.   internal val writeTimeoutMillis: Int
  10. ) : Interceptor.Chain {
  11. ···省略代码···
  12.   private var calls: Int = 0
  13.   override fun call(): Call = call
  14.   override fun request(): Request = request
  15.   @Throws(IOException::class)
  16.   override fun proceed(request: Request): Response {
  17.     check(index < interceptors.size)
  18.     calls++
  19.     if (exchange != null) {
  20.       check(exchange.finder.sameHostAndPort(request.url)) {
  21.         "network interceptor ${interceptors[index - 1]} must retain the same host and port"
  22.       }
  23.       check(calls == 1) {
  24.         "network interceptor ${interceptors[index - 1]} must call proceed() exactly once"
  25.       }
  26.     }
  27.     //index+1, 复制创建新的责任链,也就意味着调用责任链中的下一个处理者,也就是下一个拦截器
  28.     val next = copy(index = index + 1, request = request)
  29.     //取出当前拦截器
  30.     val interceptor = interceptors[index]
  31.     //执行当前拦截器的拦截方法
  32.     @Suppress("USELESS_ELVIS")
  33.     val response = interceptor.intercept(next) ?: throw NullPointerException(
  34.         "interceptor $interceptor returned null")
  35.     if (exchange != null) {
  36.       check(index + 1 >= interceptors.size || next.calls == 1) {
  37.         "network interceptor $interceptor must call proceed() exactly once"
  38.       }
  39.     }
  40.     check(response.body != null) { "interceptor $interceptor returned a response with no body" }
  41.     return response
  42.   }
  43. }
复制代码
链式调用,最终会向下执行拦截器列表中的每个拦截器,然后向上返回Response。

七、拦截器

各类拦截器的总结,按顺序:
    client.interceptors:这是由开发者设置的,会在所有的拦截器处理之前进行最早的拦截处理,可用于添加一些公共参数,如自定义header、自定义log等等。RetryAndFollowUpInterceptor:这里会对连接做一些初始化工作,以及请求失败的重试工作,重定向的后续请求工作。跟他的名字一样,就是做重试工作还有一些连接跟踪工作。BridgeInterceptor:是客户端与服务器之间的沟通桥梁,负责将用户构建的请求转换为服务器需要的请求,以及将网络请求返回回来的响应转换为用户可用的响应。CacheInterceptor:这里主要是缓存的相关处理,会根据用户在OkHttpClient里定义的缓存配置,然后结合请求新建一个缓存策略,由它来判断是使用网络还是缓存来构建response。ConnectInterceptor:这里主要就是负责建立连接,会建立TCP连接或者TLS连接。Client.networkInterceptors:这里也是开发者自己设置的,所以本质上和第一个拦截器差不多,但是由于位置不同,所以用处也不同。CallServerInterceptor:这里就是进行网络数据的请求和响应了,也就是实际的网络I/O操作,将请求头与请求体发送给服务器,以及解析服务器返回的response。
接下来我们按顺序,从上往下,对这些拦截器进行一一解读。

1.client.interceptors

这是用户自己定义的拦截器,称为应用拦截器,会保存在OkHttpClient的interceptors: List<Interceptor>列表中。 他是拦截器责任链中的第一个拦截器,也就是说会第一个执行拦截方法,我们可以通过它来添加自定义Header信息,如:
  1. class HeaderInterceptor implements Interceptor {
  2.     @Override
  3.     public Response intercept(Chain chain) throws IOException {
  4.         Request request = chain.request().newBuilder()
  5.                 .addHeader("device-android", "xxxxxxxxxxx")
  6.                 .addHeader("country-code", "ZH")
  7.                 .build();
  8.         return chain.proceed(request);
  9.     }
  10. }
  11. //然后在 OkHttpClient 中加入
  12. OkHttpClient client = new OkHttpClient.Builder()
  13.     .connectTimeout(60, TimeUnit.SECONDS)
  14.     .readTimeout(15, TimeUnit.SECONDS)
  15.     .writeTimeout(15, TimeUnit.SECONDS)
  16.     .cookieJar(new MyCookieJar())
  17.     .addInterceptor(new HeaderInterceptor())//添加自定义Header拦截器
  18.     .build();
复制代码
2.RetryAndFollowUpInterceptor

第二个拦截器,从它的名字也可知道,它负责请求失败的重试工作与重定向的后续请求工作,同时它会对连接做一些初始化工作。
  1. class RetryAndFollowUpInterceptor(private val client: OkHttpClient) : Interceptor {
  2.   @Throws(IOException::class)
  3.   override fun intercept(chain: Interceptor.Chain): Response {
  4.     val realChain = chain as RealInterceptorChain
  5.     var request = chain.request
  6.     val call = realChain.call
  7.     var followUpCount = 0
  8.     var priorResponse: Response? = null
  9.     var newExchangeFinder = true
  10.     var recoveredFailures = listOf<IOException>()
  11.     while (true) {
  12.       //这里会新建一个ExchangeFinder,ConnectInterceptor会使用到
  13.       call.enterNetworkInterceptorExchange(request, newExchangeFinder)
  14.       var response: Response
  15.       var closeActiveExchange = true
  16.       try {
  17.         if (call.isCanceled()) {
  18.           throw IOException("Canceled")
  19.         }
  20.         try {
  21.           response = realChain.proceed(request)
  22.           newExchangeFinder = true
  23.         } catch (e: RouteException) {
  24.           //尝试通过路由连接失败。该请求将不会被发送。
  25.           if (!recover(e.lastConnectException, call, request, requestSendStarted = false)) {
  26.             throw e.firstConnectException.withSuppressed(recoveredFailures)
  27.           } else {
  28.             recoveredFailures += e.firstConnectException
  29.           }
  30.           newExchangeFinder = false
  31.           continue
  32.         } catch (e: IOException) {
  33.           //尝试与服务器通信失败。该请求可能已发送。
  34.           if (!recover(e, call, request, requestSendStarted = e !is ConnectionShutdownException)) {
  35.             throw e.withSuppressed(recoveredFailures)
  36.           } else {
  37.             recoveredFailures += e
  38.           }
  39.           newExchangeFinder = false
  40.           continue
  41.         }
  42.         // Attach the prior response if it exists. Such responses never have a body.
  43.         //尝试关联上一个response,注意:body是为null
  44.         if (priorResponse != null) {
  45.           response = response.newBuilder()
  46.               .priorResponse(priorResponse.newBuilder()
  47.                   .body(null)
  48.                   .build())
  49.               .build()
  50.         }
  51.         val exchange = call.interceptorScopedExchange
  52.         //会根据 responseCode 来判断,构建一个新的request并返回来重试或者重定向
  53.         val followUp = followUpRequest(response, exchange)
  54.         if (followUp == null) {
  55.           if (exchange != null && exchange.isDuplex) {
  56.             call.timeoutEarlyExit()
  57.           }
  58.           closeActiveExchange = false
  59.           return response
  60.         }
  61.         //如果请求体是一次性的,不需要再次重试
  62.         val followUpBody = followUp.body
  63.         if (followUpBody != null && followUpBody.isOneShot()) {
  64.           closeActiveExchange = false
  65.           return response
  66.         }
  67.         response.body?.closeQuietly()
  68.         //最大重试次数,不同的浏览器是不同的,比如:Chrome为21,Safari则是16
  69.         if (++followUpCount > MAX_FOLLOW_UPS) {
  70.           throw ProtocolException("Too many follow-up requests: $followUpCount")
  71.         }
  72.         request = followUp
  73.         priorResponse = response
  74.       } finally {
  75.         call.exitNetworkInterceptorExchange(closeActiveExchange)
  76.       }
  77.     }
  78.   }
  79.   /** 判断是否要进行重连,false->不尝试重连;true->尝试重连。*/
  80.   private fun recover(
  81.     e: IOException,
  82.     call: RealCall,
  83.     userRequest: Request,
  84.     requestSendStarted: Boolean
  85.   ): Boolean {
  86.     //客户端禁止重试
  87.     if (!client.retryOnConnectionFailure) return false
  88.     //不能再次发送该请求体
  89.     if (requestSendStarted && requestIsOneShot(e, userRequest)) return false
  90.     //发生的异常是致命的,无法恢复,如:ProtocolException
  91.     if (!isRecoverable(e, requestSendStarted)) return false
  92.     //没有更多的路由来尝试重连
  93.     if (!call.retryAfterFailure()) return false
  94.     // 对于失败恢复,使用带有新连接的相同路由选择器
  95.     return true
  96.   }
  97. ···省略代码···
复制代码
3.BridgeInterceptor

从它的名字可以看出,他的定位是客户端与服务器之间的沟通桥梁,负责将用户构建的请求转换为服务器需要的请求,比如:添加Content-Type,添加Cookie,添加User-Agent等等。再将服务器返回的response做一些处理转换为客户端需要的response。比如:移除响应头中的Content-Encoding、Content-Length等等。
  1. class BridgeInterceptor(private val cookieJar: CookieJar) : Interceptor {
  2.   @Throws(IOException::class)
  3.   override fun intercept(chain: Interceptor.Chain): Response {
  4.     //获取原始请求数据
  5.     val userRequest = chain.request()
  6.     val requestBuilder = userRequest.newBuilder()
  7.     //重新构建请求头,请求体信息
  8.     val body = userRequest.body
  9.     val contentType = body.contentType()
  10.     requestBuilder.header("Content-Type", contentType.toString())
  11.     requestBuilder.header("Content-Length", contentLength.toString())
  12.     requestBuilder.header("Transfer-Encoding", "chunked")
  13.     requestBuilder.header("Host", userRequest.url.toHostHeader())
  14.     requestBuilder.header("Connection", "Keep-Alive")
  15.    ···省略代码···
  16.     //添加cookie
  17.     val cookies = cookieJar.loadForRequest(userRequest.url)
  18.     if (cookies.isNotEmpty()) {
  19.       requestBuilder.header("Cookie", cookieHeader(cookies))
  20.     }
  21.     //添加user-agent
  22.     if (userRequest.header("User-Agent") == null) {
  23.       requestBuilder.header("User-Agent", userAgent)
  24.     }
  25.     //重新构建一个Request,然后执行下一个拦截器来处理该请求
  26.     val networkResponse = chain.proceed(requestBuilder.build())
  27.     cookieJar.receiveHeaders(userRequest.url, networkResponse.headers)
  28.     //创建一个新的responseBuilder,目的是将原始请求数据构建到response中
  29.     val responseBuilder = networkResponse.newBuilder()
  30.         .request(userRequest)
  31.     if (transparentGzip &&
  32.         "gzip".equals(networkResponse.header("Content-Encoding"), ignoreCase = true) &&
  33.         networkResponse.promisesBody()) {
  34.       val responseBody = networkResponse.body
  35.       if (responseBody != null) {
  36.         val gzipSource = GzipSource(responseBody.source())
  37.         val strippedHeaders = networkResponse.headers.newBuilder()
  38.             .removeAll("Content-Encoding")
  39.             .removeAll("Content-Length")
  40.             .build()
  41.         //修改response header信息,移除Content-Encoding,Content-Length信息
  42.         responseBuilder.headers(strippedHeaders)
  43.         val contentType = networkResponse.header("Content-Type")
  44.         //修改response body信息
  45.         responseBuilder.body(RealResponseBody(contentType, -1L, gzipSource.buffer()))
  46.       }
  47.     }
  48.     return responseBuilder.build()
  49. ···省略代码···
复制代码
4.CacheInterceptor

用户可以通过OkHttpClient.cache来配置缓存,缓存拦截器通过CacheStrategy来判断是使用网络还是缓存来构建response。
  1. class CacheInterceptor(internal val cache: Cache?) : Interceptor {
  2.   @Throws(IOException::class)
  3.   override fun intercept(chain: Interceptor.Chain): Response {
  4.     val call = chain.call()
  5.     //通过request从OkHttpClient.cache中获取缓存
  6.     val cacheCandidate = cache?.get(chain.request())
  7.     val now = System.currentTimeMillis()
  8.     //创建一个缓存策略,用来确定怎么使用缓存
  9.     val strategy = CacheStrategy.Factory(now, chain.request(), cacheCandidate).compute()
  10.     //为空表示不使用网络,反之,则表示使用网络
  11.     val networkRequest = strategy.networkRequest
  12.     //为空表示不使用缓存,反之,则表示使用缓存
  13.     val cacheResponse = strategy.cacheResponse
  14.     //追踪网络与缓存的使用情况
  15.     cache?.trackResponse(strategy)
  16.     val listener = (call as? RealCall)?.eventListener ?: EventListener.NONE
  17.     //有缓存但不适用,关闭它
  18.     if (cacheCandidate != null && cacheResponse == null) {
  19.       cacheCandidate.body?.closeQuietly()
  20.     }
  21.     //如果网络被禁止,但是缓存又是空的,构建一个code为504的response,并返回
  22.     if (networkRequest == null && cacheResponse == null) {
  23.       return Response.Builder()
  24.           .request(chain.request())
  25.           .protocol(Protocol.HTTP_1_1)
  26.           .code(HTTP_GATEWAY_TIMEOUT)
  27.           .message("Unsatisfiable Request (only-if-cached)")
  28.           .body(EMPTY_RESPONSE)
  29.           .sentRequestAtMillis(-1L)
  30.           .receivedResponseAtMillis(System.currentTimeMillis())
  31.           .build().also {
  32.             listener.satisfactionFailure(call, it)
  33.           }
  34.     }
  35.     //如果我们禁用了网络不使用网络,且有缓存,直接根据缓存内容构建并返回response
  36.     if (networkRequest == null) {
  37.       return cacheResponse!!.newBuilder()
  38.           .cacheResponse(stripBody(cacheResponse))
  39.           .build().also {
  40.             listener.cacheHit(call, it)
  41.           }
  42.     }
  43.     //为缓存添加监听
  44.     if (cacheResponse != null) {
  45.       listener.cacheConditionalHit(call, cacheResponse)
  46.     } else if (cache != null) {
  47.       listener.cacheMiss(call)
  48.     }
  49.     var networkResponse: Response? = null
  50.     try {
  51.       //责任链往下处理,从服务器返回response 赋值给 networkResponse
  52.       networkResponse = chain.proceed(networkRequest)
  53.     } finally {
  54.       //捕获I/O或其他异常,请求失败,networkResponse为空,且有缓存的时候,不暴露缓存内容。
  55.       if (networkResponse == null && cacheCandidate != null) {
  56.         cacheCandidate.body?.closeQuietly()
  57.       }
  58.     }
  59.     //如果有缓存
  60.     if (cacheResponse != null) {
  61.       //且网络返回response code为304的时候,使用缓存内容新构建一个Response返回。
  62.       if (networkResponse?.code == HTTP_NOT_MODIFIED) {
  63.         val response = cacheResponse.newBuilder()
  64.             .headers(combine(cacheResponse.headers, networkResponse.headers))
  65.             .sentRequestAtMillis(networkResponse.sentRequestAtMillis)
  66.             .receivedResponseAtMillis(networkResponse.receivedResponseAtMillis)
  67.             .cacheResponse(stripBody(cacheResponse))
  68.             .networkResponse(stripBody(networkResponse))
  69.             .build()
  70.         networkResponse.body!!.close()
  71.         // Update the cache after combining headers but before stripping the
  72.         // Content-Encoding header (as performed by initContentStream()).
  73.         cache!!.trackConditionalCacheHit()
  74.         cache.update(cacheResponse, response)
  75.         return response.also {
  76.           listener.cacheHit(call, it)
  77.         }
  78.       } else {
  79.         //否则关闭缓存响应体
  80.         cacheResponse.body?.closeQuietly()
  81.       }
  82.     }
  83.     //构建网络请求的response
  84.     val response = networkResponse!!.newBuilder()
  85.         .cacheResponse(stripBody(cacheResponse))
  86.         .networkResponse(stripBody(networkResponse))
  87.         .build()
  88.     //如果cache不为null,即用户在OkHttpClient中配置了缓存,则将上一步新构建的网络请求response存到cache中
  89.     if (cache != null) {
  90.       //根据response的code,header以及CacheControl.noStore来判断是否可以缓存
  91.       if (response.promisesBody() && CacheStrategy.isCacheable(response, networkRequest)) {
  92.         // 将该response存入缓存
  93.         val cacheRequest = cache.put(response)
  94.         return cacheWritingResponse(cacheRequest, response).also {
  95.           if (cacheResponse != null) {
  96.             listener.cacheMiss(call)
  97.           }
  98.         }
  99.       }
  100.       //根据请求方法来判断缓存是否有效,只对Get请求进行缓存,其它方法的请求则移除
  101.       if (HttpMethod.invalidatesCache(networkRequest.method)) {
  102.         try {
  103.           //缓存无效,将该请求缓存从client缓存配置中移除
  104.           cache.remove(networkRequest)
  105.         } catch (_: IOException) {
  106.           // The cache cannot be written.
  107.         }
  108.       }
  109.     }
  110.     return response
  111.   }
  112. ···省略代码···  
复制代码
5.ConnectInterceptor

负责实现与服务器真正建立起连接,
  1. object ConnectInterceptor : Interceptor {
  2.   @Throws(IOException::class)
  3.   override fun intercept(chain: Interceptor.Chain): Response {
  4.     val realChain = chain as RealInterceptorChain
  5.     //初始化一个exchange对象
  6.     val exchange = realChain.call.initExchange(chain)
  7.     //根据这个exchange对象来复制创建一个新的连接责任链
  8.     val connectedChain = realChain.copy(exchange = exchange)
  9.     //执行该连接责任链
  10.     return connectedChain.proceed(realChain.request)
  11.   }
  12. }
复制代码
一扫下来,代码十分简单,拦截方法里就只有三步。
    初始化一个exchange对象。然后根据这个exchange对象来复制创建一个新的连接责任链。执行该连接责任链。
那这个exchange对象又是什么呢?
  1. RealCall.kt
  2. internal fun initExchange(chain: RealInterceptorChain): Exchange {
  3.     ...省略代码...
  4.     //这里的exchangeFinder就是在RetryAndFollowUpInterceptor中创建的
  5.     val exchangeFinder = this.exchangeFinder!!
  6.     //返回一个ExchangeCodec(是个编码器,为request编码以及为response解码)
  7.     val codec = exchangeFinder.find(client, chain)
  8.     //根据exchangeFinder与codec新构建一个Exchange对象,并返回
  9.     val result = Exchange(this, eventListener, exchangeFinder, codec)
  10.   ...省略代码...
  11.     return result
  12.   }
复制代码
具体看看ExchangeFinder.find()这一步,
  1. ExchangeFinder.kt
  2. fun find(
  3.     client: OkHttpClient,
  4.     chain: RealInterceptorChain
  5.   ): ExchangeCodec {
  6.     try {
  7.       //查找合格可用的连接,返回一个 RealConnection 对象
  8.       val resultConnection = findHealthyConnection(
  9.           connectTimeout = chain.connectTimeoutMillis,
  10.           readTimeout = chain.readTimeoutMillis,
  11.           writeTimeout = chain.writeTimeoutMillis,
  12.           pingIntervalMillis = client.pingIntervalMillis,
  13.           connectionRetryEnabled = client.retryOnConnectionFailure,
  14.           doExtensiveHealthChecks = chain.request.method != "GET"
  15.       )
  16.       //根据连接,创建并返回一个请求响应编码器:Http1ExchangeCodec 或者 Http2ExchangeCodec,分别对应Http1协议与Http2协议
  17.       return resultConnection.newCodec(client, chain)
  18.     } catch (e: RouteException) {
  19.       trackFailure(e.lastConnectException)
  20.       throw e
  21.     } catch (e: IOException) {
  22.       trackFailure(e)
  23.       throw RouteException(e)
  24.     }
  25.   }
复制代码
继续往下看findHealthyConnection方法
  1. ExchangeFinder.kt
  2.   private fun findHealthyConnection(
  3.     connectTimeout: Int,
  4.     readTimeout: Int,
  5.     writeTimeout: Int,
  6.     pingIntervalMillis: Int,
  7.     connectionRetryEnabled: Boolean,
  8.     doExtensiveHealthChecks: Boolean
  9.   ): RealConnection {
  10.     while (true) {
  11.       //重点:查找连接
  12.       val candidate = findConnection(
  13.           connectTimeout = connectTimeout,
  14.           readTimeout = readTimeout,
  15.           writeTimeout = writeTimeout,
  16.           pingIntervalMillis = pingIntervalMillis,
  17.           connectionRetryEnabled = connectionRetryEnabled
  18.       )
  19.       //检查该连接是否合格可用,合格则直接返回该连接
  20.       if (candidate.isHealthy(doExtensiveHealthChecks)) {
  21.         return candidate
  22.       }
  23.       //如果该连接不合格,标记为不可用,从连接池中移除
  24.       candidate.noNewExchanges()
  25.     ...省略代码...
  26.     }
  27.   }
复制代码
所以核心方法就是findConnection,我们继续深入看看该方法:
  1. private fun findConnection(
  2.     connectTimeout: Int,
  3.     readTimeout: Int,
  4.     writeTimeout: Int,
  5.     pingIntervalMillis: Int,
  6.     connectionRetryEnabled: Boolean
  7.   ): RealConnection {
  8.     if (call.isCanceled()) throw IOException("Canceled")
  9.     //第一次,尝试重连 call 中的 connection,不需要去重新获取连接
  10.     val callConnection = call.connection // This may be mutated by releaseConnectionNoEvents()!
  11.     if (callConnection != null) {
  12.       var toClose: Socket? = null
  13.       synchronized(callConnection) {
  14.         if (callConnection.noNewExchanges || !sameHostAndPort(callConnection.route().address.url)) {
  15.           toClose = call.releaseConnectionNoEvents()
  16.         }
  17.       }
  18.       //如果 call 中的 connection 还没有释放,就重用它。
  19.       if (call.connection != null) {
  20.         check(toClose == null)
  21.         return callConnection
  22.       }
  23.       //如果 call 中的 connection 已经被释放,关闭Socket.
  24.       toClose?.closeQuietly()
  25.       eventListener.connectionReleased(call, callConnection)
  26.     }
  27.     //需要一个新的连接,所以重置一些状态
  28.     refusedStreamCount = 0
  29.     connectionShutdownCount = 0
  30.     otherFailureCount = 0
  31.     //第二次,尝试从连接池中获取一个连接,不带路由,不带多路复用
  32.     if (connectionPool.callAcquirePooledConnection(address, call, null, false)) {
  33.       val result = call.connection!!
  34.       eventListener.connectionAcquired(call, result)
  35.       return result
  36.     }
  37.     //连接池中是空的,准备下次尝试连接的路由
  38.     val routes: List<Route>?
  39.     val route: Route
  40.     ...省略代码...
  41.       //第三次,再次尝试从连接池中获取一个连接,带路由,不带多路复用
  42.       if (connectionPool.callAcquirePooledConnection(address, call, routes, false)) {
  43.         val result = call.connection!!
  44.         eventListener.connectionAcquired(call, result)
  45.         return result
  46.       }
  47.       route = localRouteSelection.next()
  48.     }
  49.     //第四次,手动创建一个新连接
  50.     val newConnection = RealConnection(connectionPool, route)
  51.     call.connectionToCancel = newConnection
  52.     try {
  53.       newConnection.connect(
  54.           connectTimeout,
  55.           readTimeout,
  56.           writeTimeout,
  57.           pingIntervalMillis,
  58.           connectionRetryEnabled,
  59.           call,
  60.           eventListener
  61.       )
  62.     } finally {
  63.       call.connectionToCancel = null
  64.     }
  65.     call.client.routeDatabase.connected(newConnection.route())
  66.     //第五次,再次尝试从连接池中获取一个连接,带路由,带多路复用。
  67.     //这一步主要是为了校验一下,比如已经有了一条连接了,就可以直接复用,而不用使用手动创建的新连接。
  68.     if (connectionPool.callAcquirePooledConnection(address, call, routes, true)) {
  69.       val result = call.connection!!
  70.       nextRouteToTry = route
  71.       newConnection.socket().closeQuietly()
  72.       eventListener.connectionAcquired(call, result)
  73.       return result
  74.     }
  75.     synchronized(newConnection) {
  76.       //将手动创建的新连接放入连接池
  77.       connectionPool.put(newConnection)
  78.       call.acquireConnectionNoEvents(newConnection)
  79.     }
  80.     eventListener.connectionAcquired(call, newConnection)
  81.     return newConnection
  82.   }
复制代码
在代码中可以看出,一共做了5次尝试去得到连接:
    第一次,尝试重连 call 中的 connection,不需要去重新获取连接。第二次,尝试从连接池中获取一个连接,不带路由,不带多路复用。第三次,再次尝试从连接池中获取一个连接,带路由,不带多路复用。第四次,手动创建一个新连接。第五次,再次尝试从连接池中获取一个连接,带路由,带多路复用。
这一步就是为了建立连接。

6.client.networkInterceptors

该拦截器称为网络拦截器,与client.interceptors一样也是由用户自己定义的,同样是以列表的形式存在OkHttpClient中。
那这两个拦截器有什么不同呢?
其实他两的不同都是由于他们所处的位置不同所导致的,应用拦截器处于第一个位置,所以无论如何它都会被执行,而且只会执行一次。而网络拦截器处于倒数第二的位置,它不一定会被执行,而且可能会被执行多次,比如:在RetryAndFollowUpInterceptor失败或者CacheInterceptor直接返回缓存的情况下,我们的网络拦截器是不会被执行的。

7.CallServerInterceptor

到了这里,客户端与服务器已经建立好了连接,接着就是将请求头与请求体发送给服务器,以及解析服务器返回的response了。
  1. class CallServerInterceptor(private val forWebSocket: Boolean) : Interceptor {
  2.   @Throws(IOException::class)
  3.   override fun intercept(chain: Interceptor.Chain): Response {
  4.     val realChain = chain as RealInterceptorChain
  5.     val exchange = realChain.exchange!!
  6.     val request = realChain.request
  7.     val requestBody = request.body
  8.     var invokeStartEvent = true
  9.     var responseBuilder: Response.Builder? = null
  10.     try {
  11.       //写入请求头
  12.       exchange.writeRequestHeaders(request)
  13.       //如果不是GET请求,并且请求体不为空
  14.       if (HttpMethod.permitsRequestBody(request.method) && requestBody != null) {
  15.         //当请求头为"Expect: 100-continue"时,在发送请求体之前需要等待服务器返回"HTTP/1.1 100 Continue" 的response,如果没有等到该response,就不发送请求体。
  16.         //POST请求,先发送请求头,在获取到100继续状态后继续发送请求体
  17.         if ("100-continue".equals(request.header("Expect"), ignoreCase = true)) {
  18.           //刷新请求,即发送请求头
  19.           exchange.flushRequest()
  20.           //解析响应头
  21.           responseBuilder = exchange.readResponseHeaders(expectContinue = true)
  22.           exchange.responseHeadersStart()
  23.           invokeStartEvent = false
  24.         }
  25.         //写入请求体
  26.         if (responseBuilder == null) {
  27.           if (requestBody.isDuplex()) {
  28.             //如果请求体是双公体,就先发送请求头,稍后在发送请求体
  29.             exchange.flushRequest()
  30.             val bufferedRequestBody = exchange.createRequestBody(request, true).buffer()
  31.             //写入请求体
  32.             requestBody.writeTo(bufferedRequestBody)
  33.           } else {
  34.             //如果获取到了"Expect: 100-continue"响应,写入请求体
  35.             val bufferedRequestBody = exchange.createRequestBody(request, false).buffer()
  36.             requestBody.writeTo(bufferedRequestBody)
  37.             bufferedRequestBody.close()
  38.           }
  39.        ···省略代码···
  40.         //请求结束,发送请求体
  41.         exchange.finishRequest()
  42.     ···省略代码···
  43.     try {
  44.       if (responseBuilder == null) {
  45.         //读取响应头
  46.         responseBuilder = exchange.readResponseHeaders(expectContinue = false)!!
  47.         ···省略代码···
  48.       //构建一个response
  49.       var response = responseBuilder
  50.           .request(request)
  51.           .handshake(exchange.connection.handshake())
  52.           .sentRequestAtMillis(sentRequestMillis)
  53.           .receivedResponseAtMillis(System.currentTimeMillis())
  54.           .build()
  55.       var code = response.code
  56.       ···省略代码···
  57.       return response
  58. ···省略代码···
复制代码
简单概括一下:写入发送请求头,然后根据条件是否写入发送请求体,请求结束。解析服务器返回的请求头,然后构建一个新的response,并返回。 这里CallServerInterceptor是拦截器责任链中最后一个拦截器了,所以他不会再调用chain.proceed()方法往下执行,而是将这个构建的response往上传递给责任链中的每个拦截器。
总结一下流程:


到此这篇关于Java OkHttp框架源码超详细解析的文章就介绍到这了,更多相关Java OkHttp框架内容请搜索中国红客联盟以前的文章或继续浏览下面的相关文章希望大家以后多多支持中国红客联盟!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

中国红客联盟公众号

联系站长QQ:5520533

admin@chnhonker.com
Copyright © 2001-2025 Discuz Team. Powered by Discuz! X3.5 ( 粤ICP备13060014号 )|天天打卡 本站已运行