先分析同步执行的流程,简单一些:
OkHttpClient client = new OkHttpClient.Builder().build();//1
Request request = new Request.Builder()//2
.url("https://publicsuffix.org/list/public_suffix_list.dat")
.build();
client.newCall(request).execute();//3
第一步通过建造者模式创建了OkHttpClient对象,该对象可配置的一些参数:
public Builder() {
dispatcher = new Dispatcher();//调度器
protocols = DEFAULT_PROTOCOLS;//请求协议
connectionSpecs = DEFAULT_CONNECTION_SPECS;//连接配置 加密的一些东西
eventListenerFactory = EventListener.factory(EventListener.NONE);//连接的一些监听
proxySelector = ProxySelector.getDefault();
if (proxySelector == null) {
proxySelector = new NullProxySelector();
}
cookieJar = CookieJar.NO_COOKIES;//处理cookie 有cookie的话保存下载,再次请求的时候带上
socketFactory = SocketFactory.getDefault();
hostnameVerifier = OkHostnameVerifier.INSTANCE;
certificatePinner = CertificatePinner.DEFAULT;
proxyAuthenticator = Authenticator.NONE;
authenticator = Authenticator.NONE;
connectionPool = new ConnectionPool();/连接池
dns = Dns.SYSTEM;
followSslRedirects = true;
followRedirects = true;
retryOnConnectionFailure = true;
callTimeout = 0;
connectTimeout = 10_000;
readTimeout = 10_000;
writeTimeout = 10_000;
pingInterval = 0;
}
第二步同样使用建造默默是创建一个Request请求对象,配置一些请求地址和请求头的信息。
第三步首先通过
@Override public Call newCall(Request request) {
return RealCall.newRealCall(this, request, false /* for web socket */);
}
创建一个RealCall对象,这是一个可执行对象实现了Call接口,重写了execute方法和enqueue方法。对应着同步请求和异步请求。
static RealCall newRealCall(OkHttpClient client, Request originalRequest, boolean forWebSocket) {
// Safely publish the Call instance to the EventListener.
RealCall call = new RealCall(client, originalRequest, forWebSocket);
call.transmitter = new Transmitter(client, call);
return call;
}
创建RealCall的时候将OkHttpClient对象和Request对象作为参数传递给了RealCall对象同时创建了一个Transmitter对象。
/**
* Bridge between OkHttp's application and network layers. This class exposes high-level application
* layer primitives: connections, requests, responses, and streams.
*
* <p>This class supports {@linkplain #cancel asynchronous canceling}. This is intended to have the
* smallest blast radius possible. If an HTTP/2 stream is active, canceling will cancel that stream
* but not the other streams sharing its connection. But if the TLS handshake is still in progress
* then canceling may break the entire connection.
*/
这是Transmitter对象的注释,英语辣鸡简单理解下。这个类连接了应用层和网络层,该类公开了高级应用程序层原语,连接,请求,响应和流。
这个类还涉及到两个类,Exchage和ExchangeFinder,ExchangeCodec见名知意,通过ExchangeFinder能查找到Exchange,ExchangeCodec是用于请求和响应的编解码,他们和Transmitter的关系可以简单理解为:
Transmitter起到管理Exchage的作用,连接超时,发起等,Exchage起到管理请求和响应,RealConnection是可复用的真正的连接。
然后是execute函数:
@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);
}
}
一个call只能执行一次,然后触发开始请求的监听。client.dispatcher().executed(this)将这个call添加到了(runningSyncCalls.add(call);)添加到了同步执行队列中。最后是getResponseWithInterceptorChain函数:
Response getResponseWithInterceptorChain() throws IOException {
// Build a full stack of interceptors.
List<Interceptor> interceptors = new ArrayList<>();
interceptors.addAll(client.interceptors());
interceptors.add(retryAndFollowUpInterceptor);
interceptors.add(new BridgeInterceptor(client.cookieJar()));
interceptors.add(new CacheInterceptor(client.internalCache()));
interceptors.add(new ConnectInterceptor(client));
if (!forWebSocket) {
interceptors.addAll(client.networkInterceptors());
}
interceptors.add(new CallServerInterceptor(forWebSocket));
Interceptor.Chain chain = new RealInterceptorChain(interceptors, null, null, null, 0,
originalRequest, this, eventListener, client.connectTimeoutMillis(),
client.readTimeoutMillis(), client.writeTimeoutMillis());
return chain.proceed(originalRequest);
}
首先添加自己创建OkhttpClient的时候自定义的一些Interceptor,然后添加内置的几个interceptor。
RetryAndFollowUpInterceptor,负责重试和重定向。
Response intercept(Chain chain) throws IOException {
Request request = chain.request();
RealInterceptorChain realChain = (RealInterceptorChain) chain;
Transmitter transmitter = realChain.transmitter();
int followUpCount = 0;
while (true) {
//主机、端口、协议都相同时,连接可复用
transmitter.prepareToConnect(request);
//放行,让后面的拦截器执行
Response response = realChain.proceed(request, transmitter, null);
//后面的拦截器执行完了,拿到Response,解析看下是否需要重试或重定向,需要则返回新的Request
Request followUp = followUpRequest(response, route);
if (followUp == null) {
//新的Request为空,直接返回response
return response;
}
RequestBody followUpBody = followUp.body();
if (followUpBody != null && followUpBody.isOneShot()) {
//如果RequestBody有值且只许被调用一次,直接返回response
return response;
}
if (++followUpCount > MAX_FOLLOW_UPS) {
//重试次数上限,结束
throw new ProtocolException("Too many follow-up requests: " + followUpCount);
}
//将新的请求赋值给request,继续循环
request = followUp;
}
}
BridgeInterceptor,
桥接,负责把应用请求转换成网络请求,把网络响应转换成应用响应
Response intercept(Chain chain) throws IOException {
Request userRequest = chain.request();
Request.Builder requestBuilder = userRequest.newBuilder();
RequestBody body = userRequest.body();
if (body != null) {
requestBuilder.header("Content-Type", contentType.toString());
//处理Content-Length、Transfer-Encoding
//...
}
//处理Host、Connection、Accept-Encoding、Cookie、User-Agent、
//...
//放行,把处理好的新请求往下传递,得到Response
Response networkResponse = chain.proceed(requestBuilder.build());
Response.Builder responseBuilder = networkResponse.newBuilder()
.request(userRequest);
//处理新Response的Content-Encoding、Content-Length、Content-Type、gzip
//返回新Response
return responseBuilder.build();
}
CacheInterceptor,缓存拦截器
InternalCache cache;
Response intercept(Chain chain) throws IOException {
//获取候选缓存
Response cacheCandidate = cache != null
? cache.get(chain.request())
: null;
//创建缓存策略
CacheStrategy strategy =
new CacheStrategy.Factory(now, chain.request(), cacheCandidate).get();
//网络请求
Request networkRequest = strategy.networkRequest;
//缓存Response
Response cacheResponse = strategy.cacheResponse;
//如果网络请求和缓存Response都为空
if (networkRequest == null && cacheResponse == null) {
//返回一个504的Response
return new Response.Builder().code(504).xxx.build();
}
//如果不使用网络,直接返回缓存
if (networkRequest == null) {
return cacheResponse.newBuilder()
.cacheResponse(stripBody(cacheResponse)).build();
}
//放行,往后走
Response networkResponse = chain.proceed(networkRequest);
if (cacheResponse != null) {
//获取到缓存响应码304,即缓存可用
if (networkResponse.code() == HTTP_NOT_MODIFIED) {
Response response = cacheResponse.newBuilder().xxx.build();
//更新缓存,返回
cache.update(cacheResponse, response);
return response;
}
}
//获取网络Response
Response response = networkResponse.newBuilder().xxx.build();
//写入缓存,返回
cache.put(response);
return response;
}
ConnectInterceptor,负责创建连接
Response intercept(Chain chain) throws IOException {
RealInterceptorChain realChain = (RealInterceptorChain) chain;
Request request = realChain.request();
Transmitter transmitter = realChain.transmitter();
boolean doExtensiveHealthChecks = !request.method().equals("GET");
//机长创建一个交换器Exchange
Exchange exchange = transmitter.newExchange(chain, doExtensiveHealthChecks);
//放行,给下一个拦截器
return realChain.proceed(request, transmitter, exchange);
}
CallServerInterceptor,写请求和读响应拦截器
Response intercept(Chain chain) throws IOException {
RealInterceptorChain realChain = (RealInterceptorChain) chain;
Exchange exchange = realChain.exchange();
Request request = realChain.request();
//写请求头
exchange.writeRequestHeaders(request);
Response.Builder responseBuilder = null;
//处理请求体body...
//读取响应头
responseBuilder = exchange.readResponseHeaders(false);
//构建响应
Response response = responseBuilder
.request(request)
.handshake(exchange.connection().handshake())
.sentRequestAtMillis(sentRequestMillis)
.receivedResponseAtMillis(System.currentTimeMillis())
.build();
//读取响应体
response = response.newBuilder()
.body(exchange.openResponseBody(response))
.build();
return response;
}
拦截器准备好后,通过拦截器集合创建RealInterceptorChain拦截器链对象。
RealInterceptorChain实现了Interceptor.Chain接口,添加的每个拦截器实现了Intercepter接口。
最终调用拦截器链调用proceed函数。Response response = chain.proceed(originalRequest);
public Response proceed(Request request, Transmitter transmitter, @Nullable Exchange exchange)
throws IOException {
if (index >= interceptors.size()) throw new AssertionError();
calls++;
// If we already have a stream, confirm that the incoming request will use it.
if (this.exchange != null && !this.exchange.connection().supportsUrl(request.url())) {
throw new IllegalStateException("network interceptor " + interceptors.get(index - 1)
+ " must retain the same host and port");
}
// If we already have a stream, confirm that this is the only call to chain.proceed().
if (this.exchange != null && calls > 1) {
throw new IllegalStateException("network interceptor " + interceptors.get(index - 1)
+ " must call proceed() exactly once");
}
// Call the next interceptor in the chain.
RealInterceptorChain next = new RealInterceptorChain(interceptors, transmitter, exchange,
index + 1, request, call, connectTimeout, readTimeout, writeTimeout);
Interceptor interceptor = interceptors.get(index);
Response response = interceptor.intercept(next);
// Confirm that the next interceptor made its required call to chain.proceed().
if (exchange != null && index + 1 < interceptors.size() && next.calls != 1) {
throw new IllegalStateException("network interceptor " + interceptor
+ " must call proceed() exactly once");
}
// Confirm that the intercepted response isn't null.
if (response == null) {
throw new NullPointerException("interceptor " + interceptor + " returned null");
}
if (response.body() == null) {
throw new IllegalStateException(
"interceptor " + interceptor + " returned a response with no body");
}
return response;
}
众所周知的责任链模式。首先创建新的RealInterceptorChain对象,每次传入的index都会增加,获取到当前的拦截器,调用拦截器的intercept函数,每个拦截器的intercept函数前面已经列出来了。拦截器都会先对Request进行处理,然后index+1传到下一个拦截器,最终CallServerInterceptor拿到response对响应进行一些响应码的处理后再一层一层的向上一个拦截器返回response,拦截器链上的每个拦截器节点再顺序的对reponse进行处理。拦截器对request和response的处理是逆序的。
关于Transmitter,ExChange,RealConnection的理解还是很模糊。