OkHttp 3.14.10源码分析(2)- OkHttpClient - OkHttp的“ApplicationContext”

2024-01-22 16:08

本文主要是介绍OkHttp 3.14.10源码分析(2)- OkHttpClient - OkHttp的“ApplicationContext”,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

前言

在上一篇文章《OkHttp总体框架介绍》中,我简单的介绍了一下我对OkHttp总体架构设计的一个理解,在文章中,我对OkHttp的各个层次和各个关键的类都做了一个简单的介绍。那这一章节开始,我就开始从更加详细的角度去分析这些关键类的源码,那首当其冲的就是OkHttpClient。

OkHttpClient可以看作是OKHTTP的一个全局应用上下文,在一个应用中往往只会创建一个单例。它主要有两个功能

  • 可配置、存储和获取一些全局的属性配置,比如超时时间、自定义的CookieJar实现、自定义的Interceptor实现、添加事件监听等等。
  • 负责创建和管理一些全局单例对象,比如Dispatcher、ConnectionPool等。
  • 提供newCall API,我们用的最多也是这个API,例如
    String respJson = okHttpClient.newCall(request).execute().body().string();

     

OKhttpClient中大部分的代码都是其属性的配置,并没有什么逻辑上的实现,所以下面我们就从其各个属性开始,去逐步了解OKhttpClient的源码。 

属性

对于OkHttp的属性,我主要根据其特性和层次对其进行分类。但是这里不会出现上一篇文章架构图中描绘的所有类,因为那图中的类或者接口不是所有都对外开放的,一些是内部使用的API,例如:Transmitter、Exchange、Connection这些都不会出现在OKHttpClient中。

基础配置

这些属性主要是一些全局性的基础配置,它们中大部分都是对用户开放的,可获取可设置。它们会存储在OkHttp实例当中,并且会在全局范围内被各个层次的模块使用,主要是用来控制通信的一些基本行为,比如请求超时时间,是否SSL重定向,是否Http重定向,是否使用缓存、支持的协议等。

//协议簇-只支持HTTP_2/HTTP_1_1,并且不可修改
static final List<Protocol> DEFAULT_PROTOCOLS = Util.immutableList(Protocol.HTTP_2/, Protocol.HTTP_1_1);
//默认连接规范
//ConnectionSpec.CLEARTEXT:Http的规范配置
//ConnectionSpec.MODERN_TLS:TLS规范配置
static final List<ConnectionSpec> DEFAULT_CONNECTION_SPECS = Util.immutableList(ConnectionSpec.MODERN_TLS,ConnectionSpec.CLEARTEXT);
//是否SSL重定向
final boolean followSslRedirects;
//是否http重定向
final boolean followRedirects;
//请求超时(connect + write + read)默认没限制
final int callTimeout;
//连接超时(对应tcp connect())
final int connectTimeout;
//读取超时(对应TCP read())默认10s
final int readTimeout;
//写入超时(对应TCP write())默认10s
final int pingInterval;
//ping周期
final int writeTimeout;

线程资源管理层

这一层次的类只有Dispatcher一个。

final Dispatcher dispatcher;

OkHttpClient.Buider会使用其的无参构造函数创建一个默认的实现,无参构造函数会使用内置的线程池来执行异步任务。

public Builder() {dispatcher = new Dispatcher();...
}

Dispatcher主要是实现异步请求任务策略,负责分配异步线程资源,控制异步连接数,只覆盖线程资源层面的逻辑,往下的执行过程对其来说是透明的。对于同步任务,Dispatcher只是简单记录当前运行的任务实体(RealCall),并且是由RealCall主动注册和注销。
你可以通过OkHttpClient.Builder和Dispatvher有参构造函数来指定执行异步任务的线程池。

//这里出于演示目的,只是创建了一个简单的线程池,真正使用需要用户根据自己的应用场景配置自己的线程池。
Executor executor = Executors.newSingleThreadExecutor();
OkHttpClient client = new OkHttpClient.Builder().dispatcher(new Dispatcher(executor)).build();

应用层协议(Http)实现

//用户自定义拦截器,默认为空,会被添加到Interceptor调用链的最前端
final List<Interceptor> interceptors;
//用户自定义拦截器,默认为空,拦截所有非WebSocket的请求和响应。
//该集合会被添加到Connect完成后和数据发送前的中间
final List<Interceptor> networkInterceptors;
//自定义CookieJar,系统默认只有一个空实现,如果用户想实现Cookie功能,需要自己实现该接口,并且设置到OKHttpClient中。
final CookieJar cookieJar;
//实现了Http协议的缓存规范,默认为空。
final @Nullable Cache cache;

连接池

//连接池
final ConnectionPool connectionPool;

ConnectionPool是一个final类,同时它并没有实现连接池的功能,而是委派给RealConnectionPool来实现:

public final class ConnectionPool {final RealConnectionPool delegate;//默认参数public ConnectionPool() {this(5, 5, TimeUnit.MINUTES);}//用户可以通过该构造方法指定一些线程池的配置参数public ConnectionPool(int maxIdleConnections, long keepAliveDuration, TimeUnit timeUnit) {this.delegate = new RealConnectionPool(maxIdleConnections, keepAliveDuration, timeUnit);}//下面三个方法都是通过委派给RealConnection实例完成public int idleConnectionCount() {return delegate.idleConnectionCount();}...
}

ConnectionPool 虽然是不可扩展的,但是你可以通过这样的方式修改ConnectionPool 的默认参数:

OkHttpClient okHttpClient = new OkHttpClient().newBuilder()//最大空闲连接数是10,空闲连接存活时间是15分钟.connectionPool(new ConnectionPool(10,15, TimeUnit.MINUTES)).build();

传输层

//代理服务设置,默认为空
final @Nullable Proxy proxy;
//代理选择器,默认为空
//对于Proxy和ProxySelector的使用,小伙伴可以参考JDK官方文档,机翻一下应该看懂也不难。
//https://docs.oracle.com/javase/8/docs/technotes/guides/net/proxies.html
final ProxySelector proxySelector;
//Socket工厂类,默认为DefaultSocketFactory。你可以自定义自己的SocketFacotry。
final SocketFactory socketFactory;
//SSLSocket工厂类,默认SSLSocketFactoryImpl,也可以自定义。
final SSLSocketFactory sslSocketFactory;
//SSL主机名验证
final HostnameVerifier hostnameVerifier;
//下面两个是对SSL证书的处理
final CertificateChainCleaner certificateChainCleaner;
final CertificatePinner certificatePinner;
//代理权限认证
final Authenticator proxyAuthenticator;
//代理权限认证
final Authenticator authenticator;
//DNS解析
final Dns dns;

内部使用类

static {//OKHttp内部类,主要代理了一些OKHttp重用的内部API,//方便后序OKHttp升级,如果后期某个API从语义上改变了,只需要修改Internal里面相应的代理方法即可Internal.instance = new Internal() {...}
}

总结

到这里,我们就对OkHttpClient进行了一遍初略的了解,了解它到底有哪些属性,并对这些属性的作用进行了一个简单的归类,同时指出了哪些是可以自定义扩展和配置的。
在后面我们会对OkHttp其他的一些关键的实现类,进行详细的源码分析,如果文章有什么问题,也欢迎大家指出。

这篇关于OkHttp 3.14.10源码分析(2)- OkHttpClient - OkHttp的“ApplicationContext”的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/633490

相关文章

Redis连接失败:客户端IP不在白名单中的问题分析与解决方案

《Redis连接失败:客户端IP不在白名单中的问题分析与解决方案》在现代分布式系统中,Redis作为一种高性能的内存数据库,被广泛应用于缓存、消息队列、会话存储等场景,然而,在实际使用过程中,我们可能... 目录一、问题背景二、错误分析1. 错误信息解读2. 根本原因三、解决方案1. 将客户端IP添加到Re

Java汇编源码如何查看环境搭建

《Java汇编源码如何查看环境搭建》:本文主要介绍如何在IntelliJIDEA开发环境中搭建字节码和汇编环境,以便更好地进行代码调优和JVM学习,首先,介绍了如何配置IntelliJIDEA以方... 目录一、简介二、在IDEA开发环境中搭建汇编环境2.1 在IDEA中搭建字节码查看环境2.1.1 搭建步

Redis主从复制实现原理分析

《Redis主从复制实现原理分析》Redis主从复制通过Sync和CommandPropagate阶段实现数据同步,2.8版本后引入Psync指令,根据复制偏移量进行全量或部分同步,优化了数据传输效率... 目录Redis主DodMIK从复制实现原理实现原理Psync: 2.8版本后总结Redis主从复制实

锐捷和腾达哪个好? 两个品牌路由器对比分析

《锐捷和腾达哪个好?两个品牌路由器对比分析》在选择路由器时,Tenda和锐捷都是备受关注的品牌,各自有独特的产品特点和市场定位,选择哪个品牌的路由器更合适,实际上取决于你的具体需求和使用场景,我们从... 在选购路由器时,锐捷和腾达都是市场上备受关注的品牌,但它们的定位和特点却有所不同。锐捷更偏向企业级和专

Spring中Bean有关NullPointerException异常的原因分析

《Spring中Bean有关NullPointerException异常的原因分析》在Spring中使用@Autowired注解注入的bean不能在静态上下文中访问,否则会导致NullPointerE... 目录Spring中Bean有关NullPointerException异常的原因问题描述解决方案总结

python中的与时间相关的模块应用场景分析

《python中的与时间相关的模块应用场景分析》本文介绍了Python中与时间相关的几个重要模块:`time`、`datetime`、`calendar`、`timeit`、`pytz`和`dateu... 目录1. time 模块2. datetime 模块3. calendar 模块4. timeit

python-nmap实现python利用nmap进行扫描分析

《python-nmap实现python利用nmap进行扫描分析》Nmap是一个非常用的网络/端口扫描工具,如果想将nmap集成进你的工具里,可以使用python-nmap这个python库,它提供了... 目录前言python-nmap的基本使用PortScanner扫描PortScannerAsync异

Oracle数据库执行计划的查看与分析技巧

《Oracle数据库执行计划的查看与分析技巧》在Oracle数据库中,执行计划能够帮助我们深入了解SQL语句在数据库内部的执行细节,进而优化查询性能、提升系统效率,执行计划是Oracle数据库优化器为... 目录一、什么是执行计划二、查看执行计划的方法(一)使用 EXPLAIN PLAN 命令(二)通过 S

性能分析之MySQL索引实战案例

文章目录 一、前言二、准备三、MySQL索引优化四、MySQL 索引知识回顾五、总结 一、前言 在上一讲性能工具之 JProfiler 简单登录案例分析实战中已经发现SQL没有建立索引问题,本文将一起从代码层去分析为什么没有建立索引? 开源ERP项目地址:https://gitee.com/jishenghua/JSH_ERP 二、准备 打开IDEA找到登录请求资源路径位置

JAVA智听未来一站式有声阅读平台听书系统小程序源码

智听未来,一站式有声阅读平台听书系统 🌟&nbsp;开篇:遇见未来,从“智听”开始 在这个快节奏的时代,你是否渴望在忙碌的间隙,找到一片属于自己的宁静角落?是否梦想着能随时随地,沉浸在知识的海洋,或是故事的奇幻世界里?今天,就让我带你一起探索“智听未来”——这一站式有声阅读平台听书系统,它正悄悄改变着我们的阅读方式,让未来触手可及! 📚&nbsp;第一站:海量资源,应有尽有 走进“智听