之前文章大致了解了各个拦截器的作用,接下来下看责任链和这些拦截器的大体逻辑。
从上往下执行,重定向拦截器依赖下一个拦截器的响应对象,往下同理。当请求服务器请求完数据后,依次向上处理,这中间我们可以自己需求的处理。
retryAndFollowUpInterceptor:
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
// 创建StreamAllocation 是请求网络的组件对象,主要封装请求前的数据。
//注意两个参数
// client.connectionPool() 连接池,其实该对象就是一个线程池对象。
// createAddress(request.url())获取地址,有些域名可能有多个ip
streamAllocation = new StreamAllocation(
client.connectionPool(), createAddress(request.url()), callStackTrace);
int followUpCount = 0;//重连次数
Response priorResponse = null;
while (true) { // 重试的循环体
if (canceled) { // 如果取消,释放资源
streamAllocation.release();
throw new IOException("Canceled");
}
Response response = null;
boolean releaseConnection = true;
try {
// 执行下一个拦截器,桥接拦截器
response = ((RealInterceptorChain) chain).proceed(request, streamAllocation, null, null);
// 改变状态
releaseConnection = false;
} catch (RouteException e) { // 路由异常
// The attempt to connect via a route failed. The request will not have been sent.
// 判断是否是连接失败导致的异常,如果是抛出异常。
if (!recover(e.getLastConnectException(), false, request)) {
throw e.getLastConnectException();
}
// 改变状态,进行循环重试
releaseConnection = false;
continue;
} catch (IOException e) {
// An attempt to communicate with a server failed. The request may have been sent.
// 不属于连接关闭异常,
boolean requestSendStarted = !(e instanceof ConnectionShutdownException);
//判断是否可以重试
if (!recover(e, requestSendStarted, request)) throw e;
//改变状态,进入循环,重新请求
releaseConnection = false;
continue;
} finally {
// We're throwing an unchecked exception. Release any resources.
if (releaseConnection) {// 有其他异常,释放资源
streamAllocation.streamFailed(null);
streamAllocation.release();
}
}
// Attach the prior response if it exists. Such responses never have a body.
if (priorResponse != null) {// 之前的response 不为null ,封装一个新的
response = response.newBuilder()
.priorResponse(priorResponse.newBuilder()
.body(null)
.build())
.build();
}
//对response进行响应码的判断,如果需要进行重定向,那就获取新的Request
Request followUp = followUpRequest(response);
if (followUp == null) {
if (!forWebSocket) {
streamAllocation.release();
}
return response;
}
closeQuietly(response.body());
// 重定向次数大于20 释放资源
if (++followUpCount > MAX_FOLLOW_UPS) {
streamAllocation.release();
throw new ProtocolException("Too many follow-up requests: " + followUpCount);
}
if (followUp.body() instanceof UnrepeatableRequestBody) {
streamAllocation.release();
throw new HttpRetryException("Cannot retry streamed HTTP body", response.code());
}
// 判断响应对象是否和请求对象 一致
if (!sameConnection(response, followUp.url())) {
streamAllocation.release();
// 如果不一致,new 一个,重新请求
streamAllocation = new StreamAllocation(
client.connectionPool(), createAddress(followUp.url()), callStackTrace);
} else if (streamAllocation.codec() != null) {
throw new IllegalStateException("Closing the body of " + response
+ " didn't close its backing stream. Bad interceptor?");
}
request = followUp;
priorResponse = response;
}
}