继OKHttp3源码解析(三)OKHttp的任务调度Dispatcher
什么是拦截器
拦截器是OKHttp中提供一种强大机制,它可以实现网络监听,请求以及响应重写,请求失败重试等功能
当你发送一个请求的时候,OKHttp它会通过拦截器的链来执行Http请求,首先介绍OKHttp常用的拦截器
RetryAndFollowUpinterceptor 重试和失败重定向拦截器,主要做的是初始化的工作
BridgeInterceptor 桥接和适配拦截器
CacheInterceptor 缓存拦截器 这两个主要功能是补充我们用户创建请求当中缺少的一些必须的http请求头和处理缓存的一些功能
ConnectIntercetor 连接拦截器 主要负责建立可用的连接
CallServerInterceptor 主要负责把http写进我们的IO流当中,并且我们会从网络IO流当中读取服务端返给我们客户端的数据
接下来看一下同步请求用到拦截器的源码:
看一下执行execute方法里获取response中getResponseWithInterceptorChain方法
Response result = this.getResponseWithInterceptorChain();
private Response getResponseWithInterceptorChain() throws IOException {
List<Interceptor> interceptors = new ArrayList();//把所有的拦截器放到这个集合当中
interceptors.addAll(this.client.interceptors());
interceptors.add(this.retryAndFollowUpInterceptor);
interceptors.add(new BridgeInterceptor(this.client.cookieJar()));
interceptors.add(new CacheInterceptor(this.client.internalCache()));
interceptors.add(new ConnectInterceptor(this.client));
if (!this.retryAndFollowUpInterceptor.isForWebSocket()) {
interceptors.addAll(this.client.networkInterceptors());
}
interceptors.add(new CallServerInterceptor(this.retryAndFollowUpInterceptor.isForWebSocket()));
Chain chain = new RealInterceptorChain(interceptors, (StreamAllocation)null, (HttpStream)null, (Connection)null, 0, this.originalRequest);//然后将这个集合放到构造函数当中
return chain.proceed(this.originalRequest);
}
上面方法首先做的是先把这几个拦截器都添加到一个集合当中,然后放到构造方法中接下来看一下proceed方法是如何实现的
public Response proceed(Request request) throws IOException {
return this.proceed(request, this.streamAllocation, this.httpStream, this.connection);
}
public Response proceed(Request request, StreamAllocation streamAllocation, HttpStream httpStream, Connection connection) throws IOException {
if (this.index >= this.interceptors.size()) {
throw new AssertionError();
} else {
++this.calls;
if (this.httpStream != null && !this.sameConnection(request.url())) {
throw new IllegalStateException("network interceptor " + this.interceptors.get(this.index - 1) + " must retain the same host and port");
} else if (this.httpStream != null && this.calls > 1) {
throw new IllegalStateException("network interceptor " + this.interceptors.get(this.index - 1) + " must call proceed() exactly once");
} else {
//当前创建的拦截器的链,但是参数是index +1,就说下面如果需要访问的话只能从下一个拦截器开始进行访问,而不能从当前拦截器,这样做就把整个拦截器构成了一个链条
RealInterceptorChain next = new RealInterceptorChain(this.interceptors, streamAllocation, httpStream, connection, this.index + 1, request);
Interceptor interceptor = (Interceptor)this.interceptors.get(this.index);
Response response = interceptor.intercept(next);//执行索引index的intercept方法,然后将刚才所获的next拦截器的链传进去,这样就把所有的拦截器链构成了一个完整的链条
if (httpStream != null && this.index + 1 < this.interceptors.size() && next.calls != 1) {
throw new IllegalStateException("network interceptor " + interceptor + " must call proceed() exactly once");
} else if (response == null) {
throw new NullPointerException("interceptor " + interceptor + " returned null");
} else {
return response;
}
}
}
}
总结:第一步创建一系列拦截器,并将其中放入一个拦截器list集合中,第二步创建一个拦截器RealInterceptorChain,并执行拦截器链的proceed方法,proceed方法中创建下一个拦截器链,这样就会依次调用下一个拦截器的interceptor这个方法,这样就完整的构成了一个拦截器的链
首先看一下RetryAndFollowUpInterceptor拦截器中的intercept方法
public Response intercept(Chain chain) throws IOException {//主要的功能就是失败重连
Request request = chain.request();
this.streamAllocation = new StreamAllocation(this.client.connectionPool(), this.createAddress(request.url()));//用来获取连接服务端的connection和连接用于服务端的进行数据传输的输入输出流
int followUpCount = 0;
Response priorResponse = null;
while(!this.canceled) {
Response response = null;
boolean releaseConnection = true;
try {
response = ((RealInterceptorChain)chain).proceed(request, this.streamAllocation, (HttpStream)null, (Connection)null);//执行了proceed方法说明会执行下一个拦截器的interceptor方法
releaseConnection = false;
} catch (RouteException var12) {
if (!this.recover(var12.getLastConnectException(), true, request)) {
throw var12.getLastConnectException();
}
releaseConnection = false;
continue;
} catch (IOException var13) {
if (!this.recover(var13, false, request)) {
throw var13;
}
releaseConnection = false;
continue;
} finally {
if (releaseConnection) {
this.streamAllocation.streamFailed((IOException)null);
this.streamAllocation.release();
}
}
if (priorResponse != null) {
response = response.newBuilder().priorResponse(priorResponse.newBuilder().body((ResponseBody)null).build()).build();
}
Request followUp = this.followUpRequest(response);
if (followUp == null) {
if (!this.forWebSocket) {
this.streamAllocation.release();
}
return response;
}
Util.closeQuietly(response.body());
++followUpCount;
if (followUpCount > 20) {
this.streamAllocation.release();
throw new ProtocolException("Too many follow-up requests: " + followUpCount);
}
if (followUp.body() instanceof UnrepeatableRequestBody) {
throw new HttpRetryException("Cannot retry streamed HTTP body", response.code());
}
if (!this.sameConnection(response, followUp.url())) {
this.streamAllocation.release();
this.streamAllocation = new StreamAllocation(this.client.connectionPool(), this.createAddress(followUp.url()));
} else if (this.streamAllocation.stream() != null) {
throw new IllegalStateException("Closing the body of " + response + " didn't close its backing stream. Bad interceptor?");
}
request = followUp;
priorResponse = response;
}
this.streamAllocation.release();
throw new IOException("Canceled");
}
有上面方法可知第一步在发起请求前对Request进行处理,第二步调用下一个拦截器获取response,第三步对response进行处理,返回给上一个拦截器
接下来具体看一下每一个拦截器
第一个拦截器RetryAndFollowUpinterceptor (主要负责失败重连的)
进入源码查看,还是先看intercept 这个方法
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
this.streamAllocation = new StreamAllocation(this.client.connectionPool(), this.createAddress(request.url()));
//streamAllocation 就是用来建立执行Http请求所需要那些网络组件的,是用来分配Stream,它的作用获取连接服务端的Connection和用于服务端进行数据传输的输入输出流,主要传递给ConnectIntercetor所用的
int followUpCount = 0;
Response priorResponse = null;
while(!this.canceled) {
...
try {
response = ((RealInterceptorChain)chain).proceed(request, this.streamAllocation, (HttpStream)null, (Connection)null);//进行网络请求获取response
releaseConnection = false;
} catch (RouteException var12) {
...
}
++followUpCount;
if (followUpCount > 20) { //这里有重试的次数进行判断(失败的网络重连,如果超出20次就不会进行请求了,这时候就会释放streamAllocation这个对象)
this.streamAllocation.release();
throw new ProtocolException("Too many follow-up requests: " + followUpCount);
}
...
}
this.streamAllocation.release();
throw new IOException("Canceled");
}
总结:第一步创建StreamAllocation对象用来建立Http请求所需要的所有的网络的组件,它的作用就是用来分配我们的Stream,第二步调用RealInterceptorChain.proceed(...)进行网络请求,第三步根据异常结果或者响应结果判断是否要进行重新请求,第四步,调用下一个拦截器,对response进行处理,返回给上一个拦截器。
第二个拦截器BridgeInterceptor 桥接和适配拦截器
主要负责内容 设置我们的内容长度以及我们的编码方式,设置我们的压缩,添加头部等作用
public Response intercept(Chain chain) throws IOException {
Request userRequest = chain.request();
Builder requestBuilder = userRequest.newBuilder();
RequestBody body = userRequest.body();
if (body != null) {
//添加头部信息
MediaType contentType = body.contentType();
if (contentType != null) {
requestBuilder.header("Content-Type", contentType.toString());
}
long contentLength = body.contentLength();
if (contentLength != -1L) {
requestBuilder.header("Content-Length", Long.toString(contentLength));
requestBuilder.removeHeader("Transfer-Encoding");
} else {
requestBuilder.header("Transfer-Encoding", "chunked");
requestBuilder.removeHeader("Content-Length");
}
}
if (userRequest.header("Host") == null) {
requestBuilder.header("Host", Util.hostHeader(userRequest.url(), false));
}
if (userRequest.header("Connection") == null) {
requestBuilder.header("Connection", "Keep-Alive"); //默认是Keep-Alive
}
boolean transparentGzip = false;
if (userRequest.header("Accept-Encoding") == null) {
transparentGzip = true;
requestBuilder.header("Accept-Encoding", "gzip");
}
List<Cookie> cookies = this.cookieJar.loadForRequest(userRequest.url());
if (!cookies.isEmpty()) {
requestBuilder.header("Cookie", this.cookieHeader(cookies));
}
if (userRequest.header("User-Agent") == null) {
requestBuilder.header("User-Agent", Version.userAgent());
}
Response networkResponse = chain.proceed(requestBuilder.build());//调用拦截器链的proceed方法,向服务器发送请求,服务器获取到请求之后回返回给客户端response
HttpHeaders.receiveHeaders(this.cookieJar, userRequest.url(), networkResponse.headers());//所有的压缩解压的逻辑都是在这个方法里执行的,经过这个过程得到我们想要的response
okhttp3.Response.Builder responseBuilder = networkResponse.newBuilder().request(userRequest);
if (transparentGzip && "gzip".equalsIgnoreCase(networkResponse.header("Content-Encoding")) && HttpHeaders.hasBody(networkResponse)) {
//将网络请求返回给我们的response进行转化,通过判断需要满足支持Gzip压缩的告诉我们的服务器这个客户端支持Gzip压缩的这样服务端才会返回给你支持Gzip压缩的Response
//第二个判断gzip是否等于我们头部的Content-Encoding,一定要保证服务器的响应头是否支持Gzip压缩,第三步http请求头是否有body体
GzipSource responseBody = new GzipSource(networkResponse.body().source());//将Gzip的body体转换成GzipSource这个类型,目的是为了调用者使用这个reponse body体的时候直接以解压的方式来读取这个流数据
Headers strippedHeaders = networkResponse.headers().newBuilder().removeAll("Content-Encoding").removeAll("Content-Length").build();
responseBuilder.headers(strippedHeaders);
responseBuilder.body(new RealResponseBody(strippedHeaders, Okio.buffer(responseBody)));
}
return responseBuilder.build();
}
总结:第一步是负责将用户的一个Request请求转化为能够进行网络访问的请求,第二步将符合网络请求的Request进行网络请求,第三步将网络请求回来的响应Response转化为用户可用的Response
CacheInterceptor 缓存拦截器
OKHttp缓存策略 ,缓存策略的put方法
正常代码如下
OkHttpClient ok = new OkHttpClient
.Builder()
.cache(new Cache(new File("cache"),24*1024*1024)).build();
Request request = new Request.Builder().url("http://www.baidu.com").build();
Call call = ok.newCall(request);
try {
Response response = call.execute();
} catch (IOException e) {
e.printStackTrace();
}
.cache方法里面创建了一个文件名为“cache”的文件缓存大小为24*1024*1024的文件
进入源码查看
private CacheRequest put(Response response) {
String requestMethod = response.request().method();//获取requestMetohd
if (HttpMethod.invalidatesCache(response.request().method())) {
try {
this.remove(response.request());
} catch (IOException var6) {
;
}
return null;
} else if (!requestMethod.equals("GET")) {//非get方法不缓存
return null;
} else if (HttpHeaders.hasVaryAll(response)) {
return null;
} else {
Cache.Entry entry = new Cache.Entry(response); //创建Entry实例
DiskLruCache.Editor editor = null;//DiskLruCache来进行缓存的实际写入
try {
editor = this.cache.edit(urlToKey(response.request()));//用于写入缓存的
if (editor == null) {
return null;
} else {
entry.writeTo(editor);//真正的开始缓存,将我们的写入到磁盘上
return new Cache.CacheRequestImpl(editor);//主要用于后面CacheInterceptor 缓存拦截器使用的
}
} catch (IOException var7) {
this.abortQuietly(editor);
return null;
}
}
}
public void writeTo(Editor editor) throws IOException {
BufferedSink sink = Okio.buffer(editor.newSink(0));
sink.writeUtf8(this.url).writeByte(10);//缓存url
sink.writeUtf8(this.requestMethod).writeByte(10);//缓存请求方法
sink.writeDecimalLong((long)this.varyHeaders.size()).writeByte(10);//缓存头部
int i = 0;
int size;
for(size = this.varyHeaders.size(); i < size; ++i) {//遍历头部
sink.writeUtf8(this.varyHeaders.name(i)).writeUtf8(": ").writeUtf8(this.varyHeaders.value(i)).writeByte(10);
}
sink.writeUtf8((new StatusLine(this.protocol, this.code, this.message)).toString()).writeByte(10);//缓存Http响应行
sink.writeDecimalLong((long)(this.responseHeaders.size() + 2)).writeByte(10);//缓存响应的守护
i = 0;
for(size = this.responseHeaders.size(); i < size; ++i) {//遍历守护
sink.writeUtf8(this.responseHeaders.name(i)).writeUtf8(": ").writeUtf8(this.responseHeaders.value(i)).writeByte(10);
}
sink.writeUtf8(SENT_MILLIS).writeUtf8(": ").writeDecimalLong(this.sentRequestMillis).writeByte(10);//缓存发送时间
sink.writeUtf8(RECEIVED_MILLIS).writeUtf8(": ").writeDecimalLong(this.receivedResponseMillis).writeByte(10);//缓存接受响应的时间
if (this.isHttps()) {//判断我们的请求是否是Https这个请求,之后才会进行握手以及证书信息的操作
sink.writeByte(10);
sink.writeUtf8(this.handshake.cipherSuite().javaName()).writeByte(10);
this.writeCertList(sink, this.handshake.peerCertificates());
this.writeCertList(sink, this.handshake.localCertificates());
if (this.handshake.tlsVersion() != null) {
sink.writeUtf8(this.handshake.tlsVersion().javaName()).writeByte(10);
}
}
sink.close();
}
缓存策略的get方法(用来从缓存读取我们的响应体response)
Response get(Request request) {
String key = urlToKey(request);//通过url Md5解密获取key值
DiskLruCache.Snapshot snapshot;//记录缓存某一个特定时刻所包含的内容
try {
snapshot = this.cache.get(key); //通过key值来获取缓存当中
if (snapshot == null) {
return null;
}
} catch (IOException var7) {
return null;
}
Cache.Entry entry;//创建一个Entry
try {
entry = new Cache.Entry(snapshot.getSource(0));//如果通过这个key获取到这个缓存值
} catch (IOException var6) {
Util.closeQuietly(snapshot);
return null;
}
Response response = entry.response(snapshot);//通过这个entry来获取这个Response
if (!entry.matches(request, response)) {//如果一个请求和一个相应不是对应的话
Util.closeQuietly(response.body());//关闭这个流
return null;//返回空
} else {
return response;
}
}
接下来进入主题
进入源码查看
public Response intercept(Chain chain) throws IOException {
Response cacheCandidate = this.cache != null ? this.cache.get(chain.request()) : null; //如果当前缓存不为空的话去主动获取这个缓存否则执为空
long now = System.currentTimeMillis();
CacheStrategy strategy = (new Factory(now, chain.request(), cacheCandidate)).get();//缓存策略,可以使用网络也可以使用缓存进行对比来进行最好的策略
Request networkRequest = strategy.networkRequest;//通过strategy对象获取到它内部的request
Response cacheResponse = strategy.cacheResponse;//通过strategy对象获取到它内部的Response
if (this.cache != null) {
this.cache.trackResponse(strategy);//当有缓存的情况下更新一下相关的统计指标
}
if (cacheCandidate != null && cacheResponse == null) {
Util.closeQuietly(cacheCandidate.body());//当前缓存不符合要求的话就需要关闭这个
}
if (networkRequest == null && cacheResponse == null) {//当前不能使用网络的同时又没有找到相应的缓存
//通过构建者模式构建一个response,会抛出一个504这个错误
return (new Builder()).request(chain.request()).protocol(Protocol.HTTP_1_1).code(504).message("Unsatisfiable Request (only-if-cached)").body(EMPTY_BODY).sentRequestAtMillis(-1L).receivedResponseAtMillis(System.currentTimeMillis()).build();
} else if (networkRequest == null) {//当前有缓存但是不能使用网络
//直接返回我们缓存的结果
return cacheResponse.newBuilder().cacheResponse(stripBody(cacheResponse)).build();
} else {
Response networkResponse = null;
try {
networkResponse = chain.proceed(networkRequest);//通过调用拦截器的proceed方法来进行网络响应的获取,然后再交给下一个拦截器来做,下一个拦截器就是ConnectIntercetor 连接拦截器
} finally {
if (networkResponse == null && cacheCandidate != null) {
Util.closeQuietly(cacheCandidate.body());
}
}
Response response;
if (cacheResponse != null) {
if (validate(cacheResponse, networkResponse)) {//其实是判断当前network.code() 是否等于304,代表我们要从缓存中去获取
response = cacheResponse.newBuilder().headers(combine(cacheResponse.headers(), networkResponse.headers())).cacheResponse(stripBody(cacheResponse)).networkResponse(stripBody(networkResponse)).build();
networkResponse.body().close();
this.cache.trackConditionalCacheHit();
this.cache.update(cacheResponse, response);
return response;
}
Util.closeQuietly(cacheResponse.body());
}
response = networkResponse.newBuilder().cacheResponse(stripBody(cacheResponse)).networkResponse(stripBody(networkResponse)).build();
if (HttpHeaders.hasBody(response)) {//判断http头部有没有响应体
CacheRequest cacheRequest = this.maybeCache(response, networkResponse.request(), this.cache);
response = this.cacheWritingResponse(cacheRequest, response);//将我们的网络响应写入到我们的cache当中,下次取的时候就可以直接从缓存里获取了
}
return response;
}
}
ConnectIntercetor 连接拦截器(打开与服务器正式的连接,正式开启OKHttp网络请求)
查看源码
public Response intercept(Chain chain) throws IOException {
RealInterceptorChain realChain = (RealInterceptorChain)chain;
Request request = realChain.request();
StreamAllocation streamAllocation = realChain.streamAllocation();//用来建立执行Http请求所需要所有的那些网络的组件
boolean doExtensiveHealthChecks = !request.method().equals("GET");
HttpStream httpStream = streamAllocation.newStream(this.client, doExtensiveHealthChecks);//用来编码我们的request 以及解码我们的response
RealConnection connection = streamAllocation.connection();//就是用来实际网络IO传输的
return realChain.proceed(request, streamAllocation, httpStream, connection);//调用拦截器的操作
}
总结:第一步ConnectInterceptor通过拦截器链获取到前一个拦截器Interceptor传过来的StreamAllocation用来处理request,response,streamAllcation.newStream(),第二步将刚才创建的用于网络IO的Http1xStream对象,以及对于服务器交互最为关键的Http1xStream等对象传递给后面的拦截器。
public HttpStream newStream(OkHttpClient client, boolean doExtensiveHealthChecks) {
int connectTimeout = client.connectTimeoutMillis();
int readTimeout = client.readTimeoutMillis();
int writeTimeout = client.writeTimeoutMillis();
boolean connectionRetryEnabled = client.retryOnConnectionFailure();
try {
//获取RealConnection对象来进行实际的网络连接
RealConnection resultConnection = this.findHealthyConnection(connectTimeout, readTimeout, writeTimeout, connectionRetryEnabled, doExtensiveHealthChecks);
Object resultStream;
if (resultConnection.framedConnection != null) {//判断当前resultConnection是否可以复用,如果不可以复用就需要重新创建
resultStream = new Http2xStream(client, this, resultConnection.framedConnection);
} else {
resultConnection.socket().setSoTimeout(readTimeout);
resultConnection.source.timeout().timeout((long)readTimeout, TimeUnit.MILLISECONDS);
resultConnection.sink.timeout().timeout((long)writeTimeout, TimeUnit.MILLISECONDS);
//通过RealConnection 来获取resultStream对象
resultStream = new Http1xStream(client, this, resultConnection.source, resultConnection.sink);
}
ConnectionPool var9 = this.connectionPool;
synchronized(this.connectionPool) {
this.stream = (HttpStream)resultStream;
return (HttpStream)resultStream;
}
} catch (IOException var12) {
throw new RouteException(var12);
}
}
RealConnection中连接的源码如下
public void connect(int connectTimeout, int readTimeout, int writeTimeout, List<ConnectionSpec> connectionSpecs, boolean connectionRetryEnabled) {
//是否连接以及存在连接池当中
if (this.protocol != null) {//判断当前是否已经连接了,如果已经连接了就会抛出异常
throw new IllegalStateException("already connected");
} else {
RouteException routeException = null;
ConnectionSpecSelector connectionSpecSelector = new ConnectionSpecSelector(connectionSpecs);//用于选择我们的连接
if (this.route.address().sslSocketFactory() == null) {
if (!connectionSpecs.contains(ConnectionSpec.CLEARTEXT)) {
throw new RouteException(new UnknownServiceException("CLEARTEXT communication not enabled for client"));
}
String host = this.route.address().url().host();
if (!Platform.get().isCleartextTrafficPermitted(host)) {
throw new RouteException(new UnknownServiceException("CLEARTEXT communication to " + host + " not permitted by network security policy"));
}
}
while(this.protocol == null) {
try {
if (this.route.requiresTunnel()) {//是否需要建立tunnele这个隧道建立连接
this.buildTunneledConnection(connectTimeout, readTimeout, writeTimeout, connectionSpecSelector);
} else {
this.buildConnection(connectTimeout, readTimeout, writeTimeout, connectionSpecSelector);
}
} catch (IOException var9) {
Util.closeQuietly(this.socket);
Util.closeQuietly(this.rawSocket);
this.socket = null;
this.rawSocket = null;
this.source = null;
this.sink = null;
this.handshake = null;
this.protocol = null;
if (routeException == null) {
routeException = new RouteException(var9);
} else {
routeException.addConnectException(var9);
}
if (!connectionRetryEnabled || !connectionSpecSelector.connectionFailed(var9)) {
throw routeException;
}
}
}
}
}
总结:第一步创建一个RealConnection对象目的是为了实际的网络请求,第二步是否需要隧道连接或者socket连接选择不同的连接方式,第三步最后会调用CallServerInterceptor这个拦截器来完成整个OKhttp的网络请求
线程池
其实内部连接池主要做了以下几点,第一点产生一个StreamAllocation对象第二点StreamAllocation对象的弱引用添加到RealConnecttion对象的allocations集合,第三点从连接池获取
okhttp使用了GC回收算法,StreamAllocation的数量会渐渐变成0,这样就会被线程池监听到并回收,这样就可以保持多个健康的keep-alive连接
CallServerInterceptor 拦截器 (主要负责向服务器发起真正的网络请求,并接受服务返回的响应)
源码分析
public Response intercept(Chain chain) throws IOException {
HttpStream httpStream = ((RealInterceptorChain)chain).httpStream();//通过拦截器的链获取流对象
StreamAllocation streamAllocation = ((RealInterceptorChain)chain).streamAllocation();//用来建立Http请求所需要的其他的网络组件,用来分配stream
Request request = chain.request();//进行网络请求
long sentRequestMillis = System.currentTimeMillis();
httpStream.writeRequestHeaders(request);//向socket当中写入头部信息
if (HttpMethod.permitsRequestBody(request.method()) && request.body() != null) {
Sink requestBodyOut = httpStream.createRequestBody(request, request.body().contentLength());
BufferedSink bufferedRequestBody = Okio.buffer(requestBodyOut);
request.body().writeTo(bufferedRequestBody);//向socket当中写入我们的body信息
bufferedRequestBody.close();
}
httpStream.finishRequest();//完成网络请求的写入工作
Response response = httpStream.readResponseHeaders()//读取网络请求响应当中的头部信息
.request(request)
.handshake(streamAllocation.connection()
.handshake()).sentRequestAtMillis(sentRequestMillis)
.receivedResponseAtMillis(System.currentTimeMillis()).build();
if (!this.forWebSocket || response.code() != 101) {
//创建一个response体
response = response.newBuilder().body(httpStream.openResponseBody(response)).build();
}
if ("close".equalsIgnoreCase(response.request().header("Connection")) || "close".equalsIgnoreCase(response.header("Connection"))) {
//禁止新的流创建
streamAllocation.noNewStreams();
}
int code = response.code();
if ((code == 204 || code == 205) && response.body().contentLength() > 0L) {//如果获取code为204或者205抛出异常,否择传出response
throw new ProtocolException("HTTP " + code + " had non-zero Content-Length: " + response.body().contentLength());
} else {
return response;
}
}
总结:第一步向socket当中写入头部信息 第二步向socket当中写入我们的body信息 第三步读取网络请求响应当中的头部信息第四步读取response
okHttp中一次网络请求的大致过程
第一步Call对象请求封装
第二步dispatcher对请求的分发
第三步getResponseWithInterceptors()方法
通过拦截器链调用如下几个拦截器
1 RetryAndFollowUpinterceptor 重试和失败重定向拦截器 主要负责重试和重定向的请求
2 CacheInterceptor 缓存拦截器 主要负责处理缓存的拦截器
3 BridgeInterceptor 桥接和适配拦截器 负责OKhttp请求和响应对象与实际Http响应和请求之间的转换
4 ConnectIntercetor 连接拦截器 负责建立连接
5 CallServerInterceptor 拦截器 负责完成最终的网络请求