okHttp源码分析-二 RetryAndFollowUpIntercept 重定向拦截器

之前文章大致了解了各个拦截器的作用,接下来下看责任链和这些拦截器的大体逻辑。
拦截器执行的逻辑图
从上往下执行,重定向拦截器依赖下一个拦截器的响应对象,往下同理。当请求服务器请求完数据后,依次向上处理,这中间我们可以自己需求的处理。

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;
    }
  }
发布了58 篇原创文章 · 获赞 1 · 访问量 6874

猜你喜欢

转载自blog.csdn.net/chentaishan/article/details/103035168
今日推荐