带着目的阅读源码,okhttp如何执行一次网络请求呢?
本文通过samples.guide
模块中的GetExample
作为切入口。
入口
GetExample
代码如下
kotlin
class GetExample {
val client: OkHttpClient = OkHttpClient() // 创建okhttp客户端
fun run(url: String): String? {
val request: Request = Request.Builder() // 创建请求
.url(url)
.addHeader("User-Agent", "OkHttp Example")
.build() // 通过链式+build模式创建一个网络请求
return runCatching {
client.newCall(request).execute().use { response -> // 同步获取网络响应
if (!response.isSuccessful) {
null
} else {
response.body?.string()
}
}
}.getOrNull()
}
}
从上述代码可知执行一次网络请求需要如下步骤:
- step 1:创建okhttp客户端
client
kotlin
val client: OkHttpClient = OkHttpClient() // 创建okhttp客户端
- step 2:创建网络请求并配置必要参数
kotlin
val request: Request = Request.Builder() // 创建请求
.url(url)
.addHeader("User-Agent", "OkHttp Example")
.build() // 通过链式+build模式创建一个网络请求
- step 3:执行网络请求并获取网络返回
kotlin
return runCatching {
client.newCall(request).execute().use { response -> // 同步获取网络响应
if (!response.isSuccessful) {
null
} else {
response.body?.string()
}
}
}.getOrNull()
看上去是不是很简单,复杂的网络请求只需要三步即可完成,接下来我们带着问题逐步分析。
什么是okhttp客户端
OkHttp
用途
第一步中创建了OkHttpClient
对象,注释中对其的定义为:
Factory for calls, which can be used to send HTTP requests and read their responses.
用于生成Call
的工厂,Call
可以发送并接收HTTP请求。Call
是一个接口,代表一个可以执行的HTTP请求,如下:
kotlin
interface Call : Cloneable {
fun request(): Request
@Throws(IOException::class)
fun execute(): Response
fun enqueue(responseCallback: Callback)
fun isExecuted(): Boolean
fun isCanceled(): Boolean
fun timeout(): Timeout
public override fun clone(): Call
fun interface Factory {
fun newCall(request: Request): Call
}
}
OkHttp
的声明如下,除了可生成Call
之外,还可生成一个WebSocket
对象。
kotlin
open class OkHttpClient internal constructor(
builder: Builder
) : Cloneable, Call.Factory, WebSocket.Factory
WebSocket
是一个WebSocket协议的操作接口,可利用它发送基于WebSocket协议的消息,WebSocket协议是基于TCP
协议的可全双工通信的应用层网络协议,WebSocket
接口如下:
kotlin
interface WebSocket {
fun request(): Request
fun queueSize(): Long
fun send(text: String): Boolean
fun send(bytes: ByteString): Boolean
fun close(code: Int, reason: String?): Boolean
fun cancel()
fun interface Factory {
fun newWebSocket(request: Request, listener: WebSocketListener): WebSocket
}
}
总结一下:
OkHttpClient
主要用途是生成Call
对象(处理HTTP请求),生成WebSocket
对象(处理WebSocket请求)
OkHttpClient
属性
OkHttpClient
基于Builder
建造者模式,可通过链式结构清晰地设置网络配置,具体的配置项及其相应功能如下:
属性 | 功能 |
---|---|
dispatcher | 调度器,设置执行异步请求的策略。 |
connectionPool | 设置可回收复用的HTTP/HTTPS的连接池,相同地址的HTTP请求可共享一个连接。 |
interceptors | 一个可修改的拦截器列表,该列表作用于建立连接之前到选择响应源的区间。 |
networkInterceptors | 一个可修改的网络拦截器列表,该列表作用于单个请求发起到响应的区间。 |
eventListenerFactory | 可监听到该客户端网络调用中各个阶段的情况 |
retryOnConnectionFailure | 设置此客户端在遇到连接问题时是否重试,默认为true,在一些特定情况下重试 |
authenticator | 当网络返回出现授权问题时,设置授权并重试。 |
followRedirects | 设置是否重定向。 |
followSslRedirects | 设置是否允许HTTP和HTTPS协议间的重定向,优先满足followRedirects。 |
CookieJar | 设置Cookie的保存和读取机制,默认是没有Cookie处理的。 |
cache | 设置网络响应缓存,可在无网环境时读取缓存数据。 |
dns | 设置DNS服务,用于查找host于ip地址的映射。 |
proxy | 设置代理,优先级高于proxySelector。 |
proxySelector | 设置proxy选择器,可根据不同的url设置不同的选择器,当[proxy]设置为null时可用,类似PAC和全局代理。有时可通过ProxySelector防止抓包,绕过代理 。 |
proxyAuthenticator | 设置代理服务器的授权,而authenticator是设置原始服务器的授权。 |
socketFactory | 用于创建连接的sockets对象。 |
sslSocketFactory | 用于创建HTPPS连接的SSLSocket对象。 |
x509TrustManagerOrNull | X509TrustManager主要用于校验HTTPS连接中服务端的证书,一般情况下无需设置,除非使用自签名证书或者不校验。 |
connectionSpecs | 主要用于指定HTTPS连接中可支持的TLS版本和密码套件。 |
protocols | 设置请求协议。 |
hostnameVerifier | 在握手期间,主要用于校验服务器的主机名是否与证书中的主机名相符,判断该连接是否有效。 |
certificatePinner | 通过设置合法的公钥,验证服务端证书的合法性,可以将你信任的服务器证书或公钥的散列值配置到你的客户端上,只有当服务器提供的证书或公钥的散列值与客户端配置的相匹配时,才认为这个连接是安全的。称作公钥锁定或证书固定 |
certificateChainCleaner | 用于移除不匹配的TSL链接并获取受信任的证书。 |
callTimeout | 设置一次完整请求(dns解析、连接、写入request、服务端处理、获取response;包括重定向和网络重试)的超时时间。 |
connectTimeout | 设置tcp连接(和target的tcp连接)的超时时间。 |
readTimeout | 设置服务器开始发送响应数据+客户端接收完响应数据的超时时间。 |
writeTimeout | 设置客户端开始发送请求数据+服务端接收完请求数据的超时时间。 |
pingInterval | 设置连续两次自动ping之间的时间间隔,使用此参数自动发送ping帧,直到连接失败或关闭。这将使连接保持活动状态,并可以检测到连接失败,在适用于长连接的场景。 |
minWebSocketMessageToCompress | 设置WebSocket消息需要压缩的最小大小,如果设置为1024,则WebSocket消息大于1024bytes后需要压缩,否则不压缩。 |
routeDatabase | OkHttp 的一个内部机制用于追踪和管理 HTTP 连接的路由信息,无法直接设置,可以通过connectionPool() 方法获取到连接池,并通过连接池来看到具体的路由信息 |
什么是Request请求
Request
用途
Request
为一个HTTP请求,其包含了url
、method
、headers
、body
等网络所需配置。
总结
本章首先介绍如何用okhttp发送一个网络请求,然后分析OkhttpClient和Request的组成元素,后续看看okhttp是如何将请求发送出去的。