okhttp源码系列-执行一次网络请求

带着目的阅读源码,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请求,其包含了urlmethodheadersbody等网络所需配置。

总结

本章首先介绍如何用okhttp发送一个网络请求,然后分析OkhttpClient和Request的组成元素,后续看看okhttp是如何将请求发送出去的。

相关推荐
Eric_见嘉3 分钟前
真的能无限试(白)用(嫖)cursor 吗?
前端·visual studio code
DK七七33 分钟前
多端校园圈子论坛小程序,多个学校同时代理,校园小程序分展示后台管理源码
开发语言·前端·微信小程序·小程序·php
老赵的博客43 分钟前
QSS 设置bug
前端·bug·音视频
Chikaoya44 分钟前
项目中用户数据获取遇到bug
前端·typescript·vue·bug
南城夏季1 小时前
蓝领招聘二期笔记
前端·javascript·笔记
Huazie1 小时前
来花个几分钟,轻松掌握 Hexo Diversity 主题配置内容
前端·javascript·hexo
NoloveisGod1 小时前
Vue的基础使用
前端·javascript·vue.js
GISer_Jing1 小时前
前端系统设计面试题(二)Javascript\Vue
前端·javascript·vue.js
海上彼尚2 小时前
实现3D热力图
前端·javascript·3d
杨过姑父2 小时前
org.springframework.context.support.ApplicationListenerDetector 详细介绍
java·前端·spring