okhttp 源码请求流程记录

时间:2021-7-21 作者:qvyue

记录以okhttp 版本号为 3.14.9 的请求为例,看源码执行一个请求的基本流程

开始使用
        String url = "http://wwww.baidu.com";
        final Request request = new Request.Builder()
                .url(url)
                .build();
        OkHttpClient okHttpClient=new OkHttpClient();
        Call call = okHttpClient.newCall(request);
        call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                Log.d(getClass().getSimpleName(), "onFailure: ");
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                Log.d(getClass().getSimpleName(), "onResponse: " + response.code());
            }
        });

从 call.enqueue 开始 ctrl +鼠标左击可以看到Call是个接口,主要执行类为RealCall类的enqueue方法,

    public void enqueue(Callback responseCallback) {
        synchronized(this) {
            if (this.executed) {
                throw new IllegalStateException("Already Executed");
            }

            this.executed = true;
        }

        this.transmitter.callStart();
        this.client.dispatcher().enqueue(new RealCall.AsyncCall(responseCallback));
    }

根据上面代码可以看到 enqueue函数里new RealCall里的内部类AsyncCall对象,而AsyncCall是一个继承了NamedRunnable类,NamedRunnable实现了runable 接口的实现类,并且NamedRunnable类的run方法调用execute()方法,如下代码所示

public abstract class NamedRunnable implements Runnable {
    protected final String name;

    public NamedRunnable(String format, Object... args) {
        this.name = Util.format(format, args);
    }

    public final void run() {
        String oldName = Thread.currentThread().getName();
        Thread.currentThread().setName(this.name);

        try {
            this.execute();
        } finally {
            Thread.currentThread().setName(oldName);
        }

    }

    protected abstract void execute();
}

再看看AsyncCall类的execute()方法,可以从下面看到请求的结果从getResponseWithInterceptorChain方法中获取到。

protected void execute() {
            boolean signalledCallback = false;
            RealCall.this.transmitter.timeoutEnter();

            try {
              //请求结束获取到请求结果
                Response response = RealCall.this.getResponseWithInterceptorChain();
                signalledCallback = true;
                this.responseCallback.onResponse(RealCall.this, response);
            } catch (IOException var8) {
                if (signalledCallback) {
                    Platform.get().log(4, "Callback failure for " + RealCall.this.toLoggableString(), var8);
                } else {
                    this.responseCallback.onFailure(RealCall.this, var8);
                }
            } catch (Throwable var9) {
                RealCall.this.cancel();
                if (!signalledCallback) {
                    IOException canceledException = new IOException("canceled due to " + var9);
                    canceledException.addSuppressed(var9);
                    this.responseCallback.onFailure(RealCall.this, canceledException);
                }

                throw var9;
            } finally {
                RealCall.this.client.dispatcher().finished(this);
            }

        }

从下面代码可以看到getResponseWithInterceptorChain方法主要就是添加多个拦截器,并放入拦截器数组中。
下一步就是创建个拦截链类RealInterceptorChain ,并调用拦截链的proceed方法,

  Response getResponseWithInterceptorChain() throws IOException {
        List interceptors = new ArrayList();
        interceptors.addAll(this.client.interceptors());
        interceptors.add(new RetryAndFollowUpInterceptor(this.client));
        interceptors.add(new BridgeInterceptor(this.client.cookieJar()));
        interceptors.add(new CacheInterceptor(this.client.internalCache()));
        interceptors.add(new ConnectInterceptor(this.client));
        if (!this.forWebSocket) {
            interceptors.addAll(this.client.networkInterceptors());
        }

        interceptors.add(new CallServerInterceptor(this.forWebSocket));
        Chain chain = new RealInterceptorChain(interceptors, this.transmitter, (Exchange)null, 0, this.originalRequest, this, this.client.connectTimeoutMillis(), this.client.readTimeoutMillis(), this.client.writeTimeoutMillis());
        boolean calledNoMoreExchanges = false;

        Response var5;
        try {
            Response response = chain.proceed(this.originalRequest);
            if (this.transmitter.isCanceled()) {
                Util.closeQuietly(response);
                throw new IOException("Canceled");
            }

            var5 = response;
        } catch (IOException var9) {
            calledNoMoreExchanges = true;
            throw this.transmitter.noMoreExchanges(var9);
        } finally {
            if (!calledNoMoreExchanges) {
                this.transmitter.noMoreExchanges((IOException)null);
            }

        }

        return var5;
    }

从下面代码proceed方法里的操作主要就是把拦截器数组里的拦截器从第一个拦截器开始,调用拦截器的intercept方法,传入的参数为RealInterceptorChain 类本身的对象。由RealCall类的getResponseWithInterceptorChain方法可知第一个拦截器为RetryAndFollowUpInterceptor 。

    public Response proceed(Request request, Transmitter transmitter, @Nullable Exchange exchange) throws IOException {
        if (this.index >= this.interceptors.size()) {
            throw new AssertionError();
        } else {
            ++this.calls;
            if (this.exchange != null && !this.exchange.connection().supportsUrl(request.url())) {
                throw new IllegalStateException("network interceptor " + this.interceptors.get(this.index - 1) + " must retain the same host and port");
            } else if (this.exchange != null && this.calls > 1) {
                throw new IllegalStateException("network interceptor " + this.interceptors.get(this.index - 1) + " must call proceed() exactly once");
            } else {
                RealInterceptorChain next = new RealInterceptorChain(this.interceptors, transmitter, exchange, this.index + 1, request, this.call, this.connectTimeout, this.readTimeout, this.writeTimeout);//传入类本身的对象
                Interceptor interceptor = (Interceptor)this.interceptors.get(this.index);
                Response response = interceptor.intercept(next);
                if (exchange != null && this.index + 1 

从下面代码RetryAndFollowUpInterceptor类的intercept方法,做好本身的业务处理后,在调用RealInterceptorChain的proceed方法,如此流程调用完拦截器数组的每一个拦截器类。 请求服务器的链接拦截器类CallServerInterceptor,有命名名称可知为链接拦截器,主要进行与服务器之间的请求链接

 public Response intercept(Chain chain) throws IOException {
        Request request = chain.request();
        RealInterceptorChain realChain = (RealInterceptorChain)chain;
        Transmitter transmitter = realChain.transmitter();
        int followUpCount = 0;
        Response priorResponse = null;

        while(true) {
            transmitter.prepareToConnect(request);
            if (transmitter.isCanceled()) {
                throw new IOException("Canceled");
            }

            boolean success = false;

            Response response;
            try {
            //调用传入的Chain类的proceed方法,即拦截器链的对象
                response = realChain.proceed(request, transmitter, (Exchange)null);
                success = true;
            } catch (RouteException var16) {
                if (this.recover(var16.getLastConnectException(), transmitter, false, request)) {
                    continue;
                }

                throw var16.getFirstConnectException();
            } catch (IOException var17) {
                boolean requestSendStarted = !(var17 instanceof ConnectionShutdownException);
                if (!this.recover(var17, transmitter, requestSendStarted, request)) {
                    throw var17;
                }
                continue;
            } finally {
                if (!success) {
                    transmitter.exchangeDoneDueToException();
                }

            }

            if (priorResponse != null) {
                response = response.newBuilder().priorResponse(priorResponse.newBuilder().body((ResponseBody)null).build()).build();
            }

            Exchange exchange = Internal.instance.exchange(response);
            Route route = exchange != null ? exchange.connection().route() : null;
            Request followUp = this.followUpRequest(response, route);
            if (followUp == null) {
                if (exchange != null && exchange.isDuplex()) {
                    transmitter.timeoutEarlyExit();
                }

                return response;
            }

            RequestBody followUpBody = followUp.body();
            if (followUpBody != null && followUpBody.isOneShot()) {
                return response;
            }

            Util.closeQuietly(response.body());
            if (transmitter.hasExchange()) {
                exchange.detachWithViolence();
            }

            ++followUpCount;
            if (followUpCount > 20) {
                throw new ProtocolException("Too many follow-up requests: " + followUpCount);
            }

            request = followUp;
            priorResponse = response;
        }
    }

从下面CallServerInterceptor类的CallServerInterceptor方法中可以看到,该类主要做一下几方面处理

  • requestHeader 请求头处理
  • RequestBody 请求体处理
  • 后台返回responseHeader响应头处理
  • 后台返回responseBody响应体处理
    public Response intercept(Chain chain) throws IOException {
        RealInterceptorChain realChain = (RealInterceptorChain)chain;
        Exchange exchange = realChain.exchange();
        Request request = realChain.request();
        long sentRequestMillis = System.currentTimeMillis();
        exchange.writeRequestHeaders(request);
        boolean responseHeadersStarted = false;
        Builder responseBuilder = null;
        if (HttpMethod.permitsRequestBody(request.method()) && request.body() != null) {
            if ("100-continue".equalsIgnoreCase(request.header("Expect"))) {
                exchange.flushRequest();
                responseHeadersStarted = true;
                exchange.responseHeadersStart();
                responseBuilder = exchange.readResponseHeaders(true);
            }

            if (responseBuilder == null) {
                BufferedSink bufferedRequestBody;
                if (request.body().isDuplex()) {
                    exchange.flushRequest();
                    bufferedRequestBody = Okio.buffer(exchange.createRequestBody(request, true));
                    request.body().writeTo(bufferedRequestBody);
                } else {
                    bufferedRequestBody = Okio.buffer(exchange.createRequestBody(request, false));
                    request.body().writeTo(bufferedRequestBody);
                    bufferedRequestBody.close();
                }
            } else {
                exchange.noRequestBody();
                if (!exchange.connection().isMultiplexed()) {
                    exchange.noNewExchangesOnConnection();
                }
            }
        } else {
            exchange.noRequestBody();
        }

        if (request.body() == null || !request.body().isDuplex()) {
            exchange.finishRequest();
        }

        if (!responseHeadersStarted) {
            exchange.responseHeadersStart();
        }

        if (responseBuilder == null) {
            responseBuilder = exchange.readResponseHeaders(false);
        }

        Response response = responseBuilder.request(request).handshake(exchange.connection().handshake()).sentRequestAtMillis(sentRequestMillis).receivedResponseAtMillis(System.currentTimeMillis()).build();
        int code = response.code();
        if (code == 100) {
            response = exchange.readResponseHeaders(false).request(request).handshake(exchange.connection().handshake()).sentRequestAtMillis(sentRequestMillis).receivedResponseAtMillis(System.currentTimeMillis()).build();
            code = response.code();
        }

        exchange.responseHeadersEnd(response);
        if (this.forWebSocket && code == 101) {
            response = response.newBuilder().body(Util.EMPTY_RESPONSE).build();
        } else {
            response = response.newBuilder().body(exchange.openResponseBody(response)).build();
        }

        if ("close".equalsIgnoreCase(response.request().header("Connection")) || "close".equalsIgnoreCase(response.header("Connection"))) {
            exchange.noNewExchangesOnConnection();
        }

        if ((code == 204 || code == 205) && response.body().contentLength() > 0L) {
            throw new ProtocolException("HTTP " + code + " had non-zero Content-Length: " + response.body().contentLength());
        } else {
            return response;
        }
    }
声明:本文内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:qvyue@qq.com 进行举报,并提供相关证据,工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。