拦截器RetryAndFollowUpInterceptor分析

RetryAndFollowUpInterceptor拦截器

前面已经分析,okHttp的线程池里的请求任务的execute方法会构造拦截器链,然后通过index++依次调用chain.proceed方法来调用各种拦截器,不考虑用户自定义的拦截器的话,第一个被调用的拦截器就是RetryAndFollowUpInterceptor,请求重试拦截器,我们主要看被调用的方法intercept

public Response intercept(Chain chain) throws IOException {
    Request request = chain.request();
    RealInterceptorChain realChain = (RealInterceptorChain) chain;
    Call call = realChain.call();
    EventListener eventListener = realChain.eventListener();
	//StreamAllocation用于协调 连接Connections、数据流Streams 和 网络请求Calls这三个实体
    StreamAllocation streamAllocation = new StreamAllocation(client.connectionPool(),
                                                             createAddress(request.url()), call, eventListener, callStackTrace);
    this.streamAllocation = streamAllocation;
	//重定向次数
    int followUpCount = 0;
    Response priorResponse = null;
    while (true) {
        if (canceled) {
            streamAllocation.release();
            throw new IOException("Canceled");
        }

        Response response;
        boolean releaseConnection = true;
        try {
            //调用下层的拦截器做网络请求
            response = realChain.proceed(request, streamAllocation, null, null);
            releaseConnection = false;
        } catch (RouteException e) {
            //捕获RouteException,并判断本次请求的异常是否能通过重新请求来恢复(比方ProtocolException协议出错,则返回false不能重连)
            if (!recover(e.getLastConnectException(), streamAllocation, false, request)) {
                //不能则抛异常
                throw e.getFirstConnectException();
            }
            releaseConnection = false;
            //可以则continue,while循环体内重新请求一遍
            continue;
        } catch (IOException e) {
            //逻辑和上面的一样,捕获更大范围的异常
            boolean requestSendStarted = !(e instanceof ConnectionShutdownException);
            if (!recover(e, streamAllocation, requestSendStarted, request)) throw e;
            releaseConnection = false;
            continue;
        } finally {
            //释放当前的连接资源
            if (releaseConnection) {
                streamAllocation.streamFailed(null);
                streamAllocation.release();
            }
        }

        // Attach the prior response if it exists. Such responses never have a body.
        if (priorResponse != null) {
            response = response.newBuilder()
                .priorResponse(priorResponse.newBuilder()
                               .body(null)
                               .build())
                .build();
        }

        Request followUp;
        try {
            //如果上面返回了response,那么判断httpCode,具体的code做具体处理(比方407,代理认证失败,则调用代理管理类进行认证)
            followUp = followUpRequest(response, streamAllocation.route());
        } catch (IOException e) {
            streamAllocation.release();
            throw e;
        }

        //没有进一步的处理方法,(包括请求成功的)则返回null,此时直接返回response给上层处理
        if (followUp == null) {
            streamAllocation.release();
            return response;
        }

        closeQuietly(response.body());

        //重定向次数如果大于最大允许的重定向次数,则抛异常
        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();
            streamAllocation = new StreamAllocation(client.connectionPool(),
                                                    createAddress(followUp.url()), call, eventListener, callStackTrace);
            this.streamAllocation = streamAllocation;
        } 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;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值