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

相关文章

Springboot请求和响应相关注解及使用场景分析

《Springboot请求和响应相关注解及使用场景分析》本文介绍了SpringBoot中用于处理HTTP请求和构建HTTP响应的常用注解,包括@RequestMapping、@RequestParam... 目录1. 请求处理注解@RequestMapping@GetMapping, @PostMappin

Spring Boot Interceptor的原理、配置、顺序控制及与Filter的关键区别对比分析

《SpringBootInterceptor的原理、配置、顺序控制及与Filter的关键区别对比分析》本文主要介绍了SpringBoot中的拦截器(Interceptor)及其与过滤器(Filt... 目录前言一、核心功能二、拦截器的实现2.1 定义自定义拦截器2.2 注册拦截器三、多拦截器的执行顺序四、过

C++ scoped_ptr 和 unique_ptr对比分析

《C++scoped_ptr和unique_ptr对比分析》本文介绍了C++中的`scoped_ptr`和`unique_ptr`,详细比较了它们的特性、使用场景以及现代C++推荐的使用`uni... 目录1. scoped_ptr基本特性主要特点2. unique_ptr基本用法3. 主要区别对比4. u

Nginx内置变量应用场景分析

《Nginx内置变量应用场景分析》Nginx内置变量速查表,涵盖请求URI、客户端信息、服务器信息、文件路径、响应与性能等类别,这篇文章给大家介绍Nginx内置变量应用场景分析,感兴趣的朋友跟随小编一... 目录1. Nginx 内置变量速查表2. 核心变量详解与应用场景3. 实际应用举例4. 注意事项Ng

Java多种文件复制方式以及效率对比分析

《Java多种文件复制方式以及效率对比分析》本文总结了Java复制文件的多种方式,包括传统的字节流、字符流、NIO系列、第三方包中的FileUtils等,并提供了不同方式的效率比较,同时,还介绍了遍历... 目录1 背景2 概述3 遍历3.1listFiles()3.2list()3.3org.codeha

Nginx分布式部署流程分析

《Nginx分布式部署流程分析》文章介绍Nginx在分布式部署中的反向代理和负载均衡作用,用于分发请求、减轻服务器压力及解决session共享问题,涵盖配置方法、策略及Java项目应用,并提及分布式事... 目录分布式部署NginxJava中的代理代理分为正向代理和反向代理正向代理反向代理Nginx应用场景

Redis中的有序集合zset从使用到原理分析

《Redis中的有序集合zset从使用到原理分析》Redis有序集合(zset)是字符串与分值的有序映射,通过跳跃表和哈希表结合实现高效有序性管理,适用于排行榜、延迟队列等场景,其时间复杂度低,内存占... 目录开篇:排行榜背后的秘密一、zset的基本使用1.1 常用命令1.2 Java客户端示例二、zse

Redis中的AOF原理及分析

《Redis中的AOF原理及分析》Redis的AOF通过记录所有写操作命令实现持久化,支持always/everysec/no三种同步策略,重写机制优化文件体积,与RDB结合可平衡数据安全与恢复效率... 目录开篇:从日记本到AOF一、AOF的基本执行流程1. 命令执行与记录2. AOF重写机制二、AOF的

MyBatis Plus大数据量查询慢原因分析及解决

《MyBatisPlus大数据量查询慢原因分析及解决》大数据量查询慢常因全表扫描、分页不当、索引缺失、内存占用高及ORM开销,优化措施包括分页查询、流式读取、SQL优化、批处理、多数据源、结果集二次... 目录大数据量查询慢的常见原因优化方案高级方案配置调优监控与诊断总结大数据量查询慢的常见原因MyBAT

分析 Java Stream 的 peek使用实践与副作用处理方案

《分析JavaStream的peek使用实践与副作用处理方案》StreamAPI的peek操作是中间操作,用于观察元素但不终止流,其副作用风险包括线程安全、顺序混乱及性能问题,合理使用场景有限... 目录一、peek 操作的本质:有状态的中间操作二、副作用的定义与风险场景1. 并行流下的线程安全问题2. 顺