根据okhttp使用,分析每一步相关源码
OkHttpClient.Builder builder = new OkHttpClient.Builder();
HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
logging.setLevel(Constants.ISDEBUG? HttpLoggingInterceptor.Level.BODY : HttpLoggingInterceptor.Level.NONE);
OkHttpClient client = builder
.addNetworkInterceptor(new DesInterceptor())
.addInterceptor(logging)
.build();
默认配置,可根据对应参数的方法自定义配置
public Builder() {
dispatcher = new Dispatcher(); //执行异步请求的策略,内部由1个ExecutorService调用
protocols = DEFAULT_PROTOCOLS; //协议Protocol.HTTP_2和Protocol.HTTP_1_1
//连接方式ConnectionSpec.MODERN_TLS(HTTPS), ConnectionSpec.CLEARTEXT(HTTP)
connectionSpecs = DEFAULT_CONNECTION_SPECS;
/*指标事件的监听器。扩展此类以监控应用程序HTTP调用的数量,大小和持续时间
默认不处理
*/
eventListenerFactory = EventListener.factory(EventListener.NONE);
proxySelector = ProxySelector.getDefault(); //处理代理服务器,如果有
cookieJar = CookieJar.NO_COOKIES; //处理Cookie 默认不处理
socketFactory = SocketFactory.getDefault(); //创建socket
hostnameVerifier = OkHostnameVerifier.INSTANCE; //安全证书验证
certificatePinner = CertificatePinner.DEFAULT; //约束哪些证书是可信的
proxyAuthenticator = Authenticator.NONE; //处理请求头 Proxy-Authorization 默认不处理
authenticator = Authenticator.NONE; //处理请求头 Authorization 默认不处理
/*为单个用户创建一个恰当参数的连接池,参数随版本变化。
目前,该池最多可容纳5个闲置连接,闲置5分钟后将被驱逐。
public ConnectionPool() {this(5, 5, TimeUnit.MINUTES);}
*/
connectionPool = new ConnectionPool();
/*使用InetAddress.getAllByName来请求底层操作系统查找IP地址的DNS。
大多数自定义的Dns实现应该委托给这个实例
*/
dns = Dns.SYSTEM;
followSslRedirects = true; //允许从HTTPS到HTTP以及从HTTP到HTTPS的重定向。
followRedirects = true; //允许重定向
/*配置此客户端在遇到连接问题时重试或不重试。
默认情况下,此客户端将从以下问题中静默恢复:
* 无法访问的IP地址。 一个host对应多个IP。
* 陈旧的连接池。ConnectionPool重用套接字来减少请求延迟,但这些连接偶尔会超时。
* 无法访问的代理服务器。ProxySelector可用于尝试按顺序多个代理服务器,最终回落到直接连接。
*/
retryOnConnectionFailure = true;
connectTimeout = 10_000; //默认连接超时(以毫秒为单位)。
readTimeout = 10_000; //默认读取超时(以毫秒为单位)。
writeTimeout = 10_000; //默认写入超时(以毫秒为单位)。
pingInterval = 0; //Web套接字ping时间间隔(以毫秒为单位)。
}
返回观察单个网络请求和响应的拦截器的可修改列表。 这些拦截器必须调用Interceptor.Chain.proceed(okhttp3.Request)正好一次:它是一种用于在网络拦截到短路的错误或重复的网络请求。
当调用Response response = chain.proceed(request); 后,可使用下面方式重新返回Response
ResponseBody body = ResponseBody.create(mediaType, json); return response.newBuilder().body(body).build();
返回一个可修改的拦截器列表,用于观察每个调用的完整跨度:从连接建立之前(如果有)到选择响应源(源服务器,缓存或两者)之后。
OkHttpClient(Builder builder) 将Builder中的参数对应的赋值给OkHttpClient
//通过isTLS判断是否是HTTPS连接
if (builder.sslSocketFactory != null || !isTLS) {
this.sslSocketFactory = builder.sslSocketFactory;
this.certificateChainCleaner = builder.certificateChainCleaner;
} else {
X509TrustManager trustManager = systemDefaultTrustManager();
this.sslSocketFactory = systemDefaultSslSocketFactory(trustManager);
this.certificateChainCleaner = CertificateChainCleaner.get(trustManager);
}
如果使用HTTPS的话,可以通过Builder#sslSocketFactory(
SSLSocketFactory sslSocketFactory, X509TrustManager trustManager)添加自定义的证书
## 访问网络
String run(String url) throws IOException {
Request request = new Request.Builder()
.url(url)
.build();
Response response = client.newCall(request).execute();
return response.body().string();
}
Request(Builder builder) {
this.url = builder.url; //访问地址
this.method = builder.method; //请求方式 GET POST HEAD DELETE PUT PATCH
this.headers = builder.headers.build(); //请求头 Headers
this.body = builder.body; //请求体 RequestBody
this.tag = builder.tag != null ? builder.tag : this;//标签,可以用来取消请求
}
准备将来要执行的请求。
@Override public Call newCall(Request request) {
return RealCall.newRealCall(this, request, false /* for web socket */);
}
->RealCall->static RealCall newRealCall(OkHttpClient client, Request originalRequest, boolean forWebSocket) {
// 安全地将Call实例发布到EventListener。
RealCall call = new RealCall(client, originalRequest, forWebSocket);
call.eventListener = client.eventListenerFactory().create(call);
return call;
}
private RealCall(OkHttpClient client, Request originalRequest, boolean forWebSocket) {
this.client = client;
this.originalRequest = originalRequest;
this.forWebSocket = forWebSocket;
this.retryAndFollowUpInterceptor = new RetryAndFollowUpInterceptor(client, forWebSocket);
}
/*这个拦截器从故障中恢复并在必要时遵循重定向。
如果调用被取消,它可能会抛出IOException,因为底层是调用的socket.close
*/
->RetryAndFollowUpInterceptor
->public RetryAndFollowUpInterceptor(OkHttpClient client, boolean forWebSocket) {
this.client = client;
this.forWebSocket = forWebSocket;
}
同一个RealCall只能同时请求一次,不管是execute还是enqueue
同步请求
@Override public Response execute() throws IOException {
synchronized (this) {
if (executed) throw new IllegalStateException("Already Executed");
executed = true;
}
captureCallStackTrace();//在执行呼叫或排队时捕获堆栈跟踪。确定连接泄漏的来源。
eventListener.callStart(this);
try {
client.dispatcher().executed(this);
Response result = getResponseWithInterceptorChain();
if (result == null) throw new IOException("Canceled");
return result;
} catch (IOException e) {
eventListener.callFailed(this, e);
throw e;
} finally {
client.dispatcher().finished(this);
}
}
client.dispatcher().executed(this);
->synchronized void executed(RealCall call) {
runningSyncCalls.add(call);
}
//运行同步调用。包括取消尚未完成的调用。
runningSyncCalls = new ArrayDeque<>();
//Deque 线性队列(双端队列),不是线程安全的,当用作堆栈时,该类可能比Stack快,并且在用作队列时比LinkedList快。
Response result = getResponseWithInterceptorChain();
->Response getResponseWithInterceptorChain() throws IOException {
// Build a full stack of interceptors.
List interceptors = new ArrayList<>();
interceptors.addAll(client.interceptors());//创建client是配置的自定义Interceptor
interceptors.add(retryAndFollowUpInterceptor);//处理故障并恢复的拦截器
interceptors.add(new BridgeInterceptor(client.cookieJar()));//从应用程序代码到网络代码的桥梁。 主要是配置请求头信息
interceptors.add(new CacheInterceptor(client.internalCache()));//返回304使用缓存,有缓存使用缓存,没有就请求网络,并更新缓存
/*打开到目标服务器的连接并继续到下一个拦截器。
由RealConnection建立连接,
由HttpCodec对HTTP请求进行编码并对HTTP响应进行解码。
*/
interceptors.add(new ConnectInterceptor(client));
if (!forWebSocket) {//forWebSocket=false
interceptors.addAll(client.networkInterceptors());//自定义网络拦截器
}
/*这是链中的最后一个拦截器。 它会对服务器进行网络调用。
if (forWebSocket && code == 101) {返回非空响应体}
*/
interceptors.add(new CallServerInterceptor(forWebSocket));//
/*一个包含整个拦截器链的具体拦截器链:
所有应用程序拦截器(application interceptors),
OkHttp核心(OkHttp core),
所有网络拦截器(network interceptors),
最后是网络调用者(CallServerInterceptor)。
*/
Interceptor.Chain chain = new RealInterceptorChain(interceptors, null, null, null, 0,
originalRequest, this, eventListener, client.connectTimeoutMillis(),
client.readTimeoutMillis(), client.writeTimeoutMillis());
return chain.proceed(originalRequest);
}
异步请求
@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));
}
client.dispatcher().enqueue(new AsyncCall(responseCallback));
->synchronized void enqueue(AsyncCall call) {
/*maxRequests=64,maxRequestsPerHost=5
请求数小于64并且host数小于5,访问网络,否则排队
*/
if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) {
runningAsyncCalls.add(call);
executorService().execute(call);
} else {
readyAsyncCalls.add(call);//加入队列
}
}
executorService().execute(call);
//默认是一个数量无限制的线程池
->public synchronized ExecutorService executorService() {
if (executorService == null) {
executorService = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60, TimeUnit.SECONDS,
new SynchronousQueue(), Util.threadFactory("OkHttp Dispatcher", false));
}
return executorService;
}
AsyncCall
-> AsyncCall extends NamedRunnable
-> NamedRunnable implements Runnable#run()->execute()
//访问网络部分和同步请求一样,加了异步回调方法
@Override protected void execute() {
boolean signalledCallback = false;
try {
Response response = getResponseWithInterceptorChain();
if (retryAndFollowUpInterceptor.isCanceled()) {
signalledCallback = true;
responseCallback.onFailure(RealCall.this, new IOException("Canceled"));
} else {
signalledCallback = true;
responseCallback.onResponse(RealCall.this, response);
}
} catch (IOException e) {
if (signalledCallback) {
// Do not signal the callback twice!
Platform.get().log(INFO, "Callback failure for " + toLoggableString(), e);
} else {
eventListener.callFailed(RealCall.this, e);
responseCallback.onFailure(RealCall.this, e);
}
} finally {
client.dispatcher().finished(this);
}
}
}