总述
最近在学习网络相关的知识,在熟悉基础的网络知识后,今天复习一下经常用的网络请求库Okhttp的基本使用
使用和调用流程
首先我们查看文档其的基本使用,然后根据基本使用,分析其调用流程
基本使用
//创建client
OkHttpClient client = new OkHttpClient();
//构建请求
Request request = new Request.Builder()
.url(url)
.build();
//执行请求,等待返回结果
Response response = client.newCall(request).execute()
基本流程
核心类分析
简述
根据上面的流程,我们可以得到执行一次请求所使用到的核心类.它们分别是
- OkhttpClient
- ConnectionPool
- Request
- RealCall,AsyncCall
- Response
- RetryAndFollowUpInterceptor
- BridgeInterceptor
- CacheInterceptor
- ConnectInterceptor
- CallServerInterceptor
- RealInterceptorChain
OkhttpClient中的参数
- DEFAULT_PROTOCOLS =Util.immutableList( Protocol.HTTP_2, Protocol.HTTP_1_1)
- 连接的协议,Http2,Http1.1
- Protocol类里面是各种协议的定义,还有Http1.0,Quic
- DEFAULT_CONNECTION_SPECS = Util.immutableList( ConnectionSpec.MODERN_TLS, ConnectionSpec.CLEARTEXT);
- 传输加密算法设置,TLS,CLEARTEXT(不加密)
- ==Dispatcher==
- 异步请求时的配置策略
- 最大请求数64
- 默认同一个主机,最大为5
- 负责异步任务的分发
- 使用Executroservice,创建线程,进行网络请求
new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>(), Util.threadFactory("OkHttp Dispatcher", false));
- 三个队列维护请求任务
private final Deque<AsyncCall> readyAsyncCalls = new ArrayDeque<>();
/** Running asynchronous calls. Includes canceled calls that haven't finished yet. */
private final Deque<AsyncCall> runningAsyncCalls = new ArrayDeque<>();
/** Running synchronous calls. Includes canceled calls that haven't finished yet. */
private final Deque<RealCall> runningSyncCalls = new ArrayDeque<>();
- 异步请求加入是使用
//RealCall
@Override public void enqueue(Callback responseCallback) {
synchronized (this) {
if (executed) throw new IllegalStateException("Already Executed");
executed = true;
}
captureCallStackTrace();
eventListener.callStart(this);
client.dispatcher().enqueue(new AsyncCall(responseCallback));
}
- proxy
- 网络请求代理的设置
- 有三种类型,Direct,http;sock5
- protocols集合,跟默认的协议一样,这里可以自己配置
- List connectionSpecs 连接加密算法,也与上面默认配置一样
- interceptors 自定义拦截器集合
- networkInterceptors 网络拦截器
- 当设置forwebsocket 为false时,使用
if (!forWebSocket) {
interceptors.addAll(client.networkInterceptors());
}
- eventListenerFactory:网络请求过程事件监听器的创建工厂类
callStart;callEnd;responseBodyEnd;等
- ProxySelector 代理服务选择类
- CookieJar:http coookie策略
- 配置保存http cookie的策略
- 实现类ReactCookieJarContainer
@Override
public void saveFromResponse(HttpUrl url, List<Cookie> cookies) {
if (cookieJar != null) {
cookieJar.saveFromResponse(url, cookies);
}
}
- cache
- 缓存http和https的响应到文件系统,节省宽带,进行复用
Request request = new Request.Builder()
.cacheControl(new CacheControl.Builder()
.maxAge(0, TimeUnit.SECONDS)
.build())
.url("http://publicobject.com/helloworld.txt")
.build();
- 针对get和put请求
- 内部使用DiskLruCache缓存类进行控制
- internalCache:Cache的内部类,内部调用Cache的方法,
- 如果设置setChache,就会将其置空,两个只能存在一个
- socketFactory:创建socket
- sslSocketFactory:创建sslSocket,
- 这个需要自己实现,默认的工厂类都是抛出异常DefaultSSLSocketFactory
- certificateChainCleaner
- Computes the effective certificate chain from the raw array returned by Java's built in TLS APIs
- hostnameVerifier--》OkHostnameVerifier
- 主机地址校验,用于自签名证书使用
- certificatePinner
- https证书;锁定证书可以防止对证书颁发机构相关的攻击
- Pinning是每个主机名和/或每个通配符模式。要同时使用publicobject.com和www.publicobject.com,必须配置这两个主机名。
String hostname = "publicobject.com";
CertificatePinner certificatePinner = new CertificatePinner.Builder()
.add(hostname, "sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=")
.build();
OkHttpClient client = OkHttpClient.Builder()
.certificatePinner(certificatePinner)
.build();
Request request = new Request.Builder()
.url("https://" + hostname)
.build();
client.newCall(request).execute();
- Authenticator proxyAuthenticator:代理认证,
- Authenticator authenticator:网络认证
- dns:dns提供自定义dns解析,默认为系统的
- boolean followSslRedirects:ssl重定向
- boolean followRedirects:重定向
- boolean retryOnConnectionFailure失败重试
- 时间设置
final int callTimeout;
final int connectTimeout;
final int readTimeout;
final int writeTimeout;
- ==connectionPool==
- 复用http或http/2的连接; 减少网络延迟
- 使用线程池进行连接的定时统计和清理
new ThreadPoolExecutor(0 /* corePoolSize */,
Integer.MAX_VALUE /* maximumPoolSize */, 60L /* keepAliveTime */, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>(), Util.threadFactory("OkHttp ConnectionPool", true));
- idleConnectionCount():空闲连接
- RealConnection
- put();如果清理连接没有运行,启动线程检查连接;并添加连接到ArrayDeque实现的队列
void put(RealConnection connection) {
assert (Thread.holdsLock(this));
if (!cleanupRunning) {
cleanupRunning = true;
executor.execute(cleanupRunnable);
}
connections.add(connection);
}
- cleanupRunnable
- cleanup(System.nanoTime()),如来连接在规定时间没有复用,结束
- 同时统计空闲的和使用的连接
long idleDurationNs = now - connection.idleAtNanos;(默认存活时间为5)
if (longestIdleDurationNs >= this.keepAliveDurationNs
|| idleConnectionCount > this.maxIdleConnections) {
// We've found a connection to evict. Remove it from the list, then close it below (outside
// of the synchronized block).
connections.remove(longestIdleConnection);
} else if (idleConnectionCount > 0) {
// A connection will be ready to evict soon.
return keepAliveDurationNs - longestIdleDurationNs;
} else if (inUseConnectionCount > 0) {
// All connections are in use. It'll be at least the keep alive duration 'til we run again.
return keepAliveDurationNs;
} else {
// No connections, idle or in use.
cleanupRunning = false;
return -1;
}
拦截器
拦截器调用机制
- RealInterceptorChain
- index
- List interceptors
//该方法不需要重写
process(...){
//增加index生成下一个拦截器的拦截连
RealInterceptorChain next = new RealInterceptorChain(interceptors, ... index + 1, ... writeTimeout);
//处理自身的拦截条件,并传递下一个连接
Interceptor interceptor = interceptors.get(index);
Response response = interceptor.intercept(next);
}
intercept(chain) {
//处理自身的拦截条件
...
//往下传递
Response networkResponse = chain.proceed(requestBuilder.build());
//返回结果
return responseBuilder.build();
}
系统默认的拦截器
- RetryAndFollowUpInterceptor
- 处理失败和重定向下的情况
- MAX_FOLLOW_UPS:最大重定向尝试次数
- BridgeInterceptor:构建http请求头header
- CacheInterceptor:
- 从缓存里取
- 请求成功存
- ConnectInterceptor
- 连接目标服务,
HttpCodec httpCodec = streamAllocation.newStream(client, chain, doExtensiveHealthChecks);
RealConnection connection = streamAllocation.connection();
return realChain.proceed(request, streamAllocation, httpCodec, connection);
- CallServerInterceptor
- 向服务器进行网络请求