okhttp 流程分析

先分析同步执行的流程,简单一些:

OkHttpClient client = new OkHttpClient.Builder().build();//1
Request request = new Request.Builder()//2
        .url("https://publicsuffix.org/list/public_suffix_list.dat")
        .build();
client.newCall(request).execute();//3

第一步通过建造者模式创建了OkHttpClient对象,该对象可配置的一些参数:

public Builder() {
      dispatcher = new Dispatcher();//调度器
      protocols = DEFAULT_PROTOCOLS;//请求协议
      connectionSpecs = DEFAULT_CONNECTION_SPECS;//连接配置 加密的一些东西
      eventListenerFactory = EventListener.factory(EventListener.NONE);//连接的一些监听
      proxySelector = ProxySelector.getDefault();
      if (proxySelector == null) {
        proxySelector = new NullProxySelector();
      }
      cookieJar = CookieJar.NO_COOKIES;//处理cookie 有cookie的话保存下载,再次请求的时候带上
      socketFactory = SocketFactory.getDefault();
      hostnameVerifier = OkHostnameVerifier.INSTANCE;
      certificatePinner = CertificatePinner.DEFAULT;
      proxyAuthenticator = Authenticator.NONE;
      authenticator = Authenticator.NONE;
      connectionPool = new ConnectionPool();/连接池
      dns = Dns.SYSTEM;
      followSslRedirects = true;
      followRedirects = true;
      retryOnConnectionFailure = true;
      callTimeout = 0;
      connectTimeout = 10_000;
      readTimeout = 10_000;
      writeTimeout = 10_000;
      pingInterval = 0;
    }

第二步同样使用建造默默是创建一个Request请求对象,配置一些请求地址和请求头的信息。

第三步首先通过

@Override public Call newCall(Request request) {
    return RealCall.newRealCall(this, request, false /* for web socket */);
  }

创建一个RealCall对象,这是一个可执行对象实现了Call接口,重写了execute方法和enqueue方法。对应着同步请求和异步请求。

static RealCall newRealCall(OkHttpClient client, Request originalRequest, boolean forWebSocket) {
    // Safely publish the Call instance to the EventListener.
    RealCall call = new RealCall(client, originalRequest, forWebSocket);
    call.transmitter = new Transmitter(client, call);
    return call;
  }

创建RealCall的时候将OkHttpClient对象和Request对象作为参数传递给了RealCall对象同时创建了一个Transmitter对象。

/**
 * Bridge between OkHttp's application and network layers. This class exposes high-level application
 * layer primitives: connections, requests, responses, and streams.
 *
 * <p>This class supports {@linkplain #cancel asynchronous canceling}. This is intended to have the
 * smallest blast radius possible. If an HTTP/2 stream is active, canceling will cancel that stream
 * but not the other streams sharing its connection. But if the TLS handshake is still in progress
 * then canceling may break the entire connection.
 */

这是Transmitter对象的注释,英语辣鸡简单理解下。这个类连接了应用层和网络层,该类公开了高级应用程序层原语,连接,请求,响应和流。

这个类还涉及到两个类,Exchage和ExchangeFinder,ExchangeCodec见名知意,通过ExchangeFinder能查找到Exchange,ExchangeCodec是用于请求和响应的编解码,他们和Transmitter的关系可以简单理解为:

Transmitter起到管理Exchage的作用,连接超时,发起等,Exchage起到管理请求和响应,RealConnection是可复用的真正的连接。

然后是execute函数:

@Override public Response execute() throws IOException {
    synchronized (this) {
      if (executed) throw new IllegalStateException("Already Executed");
      executed = true;
    }
    captureCallStackTrace();
    eventListener.callStart(this);
    try {
      client.dispatcher().executed(this);
      Response result = getResponseWithInterceptorChain();
      if (result == null) throw new IOException("Canceled");
      return result;
    } catch (IOException e) {
      eventListener.callFailed(this, e);
      throw e;
    } finally {
      client.dispatcher().finished(this);
    }
  }

一个call只能执行一次,然后触发开始请求的监听。client.dispatcher().executed(this)将这个call添加到了(runningSyncCalls.add(call);)添加到了同步执行队列中。最后是getResponseWithInterceptorChain函数:

Response getResponseWithInterceptorChain() throws IOException {
    // Build a full stack of interceptors.
    List<Interceptor> interceptors = new ArrayList<>();
    interceptors.addAll(client.interceptors());
    interceptors.add(retryAndFollowUpInterceptor);
    interceptors.add(new BridgeInterceptor(client.cookieJar()));
    interceptors.add(new CacheInterceptor(client.internalCache()));
    interceptors.add(new ConnectInterceptor(client));
    if (!forWebSocket) {
      interceptors.addAll(client.networkInterceptors());
    }
    interceptors.add(new CallServerInterceptor(forWebSocket));

    Interceptor.Chain chain = new RealInterceptorChain(interceptors, null, null, null, 0,
        originalRequest, this, eventListener, client.connectTimeoutMillis(),
        client.readTimeoutMillis(), client.writeTimeoutMillis());

    return chain.proceed(originalRequest);
  }

首先添加自己创建OkhttpClient的时候自定义的一些Interceptor,然后添加内置的几个interceptor。

RetryAndFollowUpInterceptor,负责重试和重定向。

Response intercept(Chain chain) throws IOException {
    Request request = chain.request();
    RealInterceptorChain realChain = (RealInterceptorChain) chain;
    Transmitter transmitter = realChain.transmitter();
    int followUpCount = 0;
    while (true) {
        //主机、端口、协议都相同时,连接可复用
        transmitter.prepareToConnect(request);
        //放行,让后面的拦截器执行
        Response response = realChain.proceed(request, transmitter, null);
        //后面的拦截器执行完了,拿到Response,解析看下是否需要重试或重定向,需要则返回新的Request
        Request followUp = followUpRequest(response, route);
        if (followUp == null) {
            //新的Request为空,直接返回response
            return response;
        }
        RequestBody followUpBody = followUp.body();
        if (followUpBody != null && followUpBody.isOneShot()) {
            //如果RequestBody有值且只许被调用一次,直接返回response
            return response;
        }
        if (++followUpCount > MAX_FOLLOW_UPS) {
            //重试次数上限,结束
            throw new ProtocolException("Too many follow-up requests: " + followUpCount);
        }
        //将新的请求赋值给request,继续循环
        request = followUp;
    }
}

BridgeInterceptor,桥接,负责把应用请求转换成网络请求,把网络响应转换成应用响应

Response intercept(Chain chain) throws IOException {
    Request userRequest = chain.request();
    Request.Builder requestBuilder = userRequest.newBuilder();
    RequestBody body = userRequest.body();
    if (body != null) {
        requestBuilder.header("Content-Type", contentType.toString());
        //处理Content-Length、Transfer-Encoding
        //...
    }
    //处理Host、Connection、Accept-Encoding、Cookie、User-Agent、
    //...
    //放行,把处理好的新请求往下传递,得到Response
    Response networkResponse = chain.proceed(requestBuilder.build());
    Response.Builder responseBuilder = networkResponse.newBuilder()
        .request(userRequest);
	//处理新Response的Content-Encoding、Content-Length、Content-Type、gzip
    //返回新Response
    return responseBuilder.build();
}

CacheInterceptor,缓存拦截器

InternalCache cache;
Response intercept(Chain chain) throws IOException {
    //获取候选缓存
    Response cacheCandidate = cache != null
        ? cache.get(chain.request())
        : null;
    //创建缓存策略
    CacheStrategy strategy = 
        new CacheStrategy.Factory(now, chain.request(), cacheCandidate).get();
    //网络请求
    Request networkRequest = strategy.networkRequest;
    //缓存Response
    Response cacheResponse = strategy.cacheResponse;
    //如果网络请求和缓存Response都为空
    if (networkRequest == null && cacheResponse == null) {
        //返回一个504的Response
        return new Response.Builder().code(504).xxx.build();
    }
    //如果不使用网络,直接返回缓存
    if (networkRequest == null) {
        return cacheResponse.newBuilder()
            .cacheResponse(stripBody(cacheResponse)).build();
    }
    //放行,往后走
    Response networkResponse = chain.proceed(networkRequest);
    if (cacheResponse != null) {
        //获取到缓存响应码304,即缓存可用
        if (networkResponse.code() == HTTP_NOT_MODIFIED) {
            Response response = cacheResponse.newBuilder().xxx.build();
            //更新缓存,返回
            cache.update(cacheResponse, response);
            return response;
        }
    }
    //获取网络Response
    Response response = networkResponse.newBuilder().xxx.build();
    //写入缓存,返回
    cache.put(response);
    return response;
}

ConnectInterceptor,负责创建连接


Response intercept(Chain chain) throws IOException {
    RealInterceptorChain realChain = (RealInterceptorChain) chain;
    Request request = realChain.request();
    Transmitter transmitter = realChain.transmitter();
    boolean doExtensiveHealthChecks = !request.method().equals("GET");
    //机长创建一个交换器Exchange
    Exchange exchange = transmitter.newExchange(chain, doExtensiveHealthChecks);
    //放行,给下一个拦截器
    return realChain.proceed(request, transmitter, exchange);
}

CallServerInterceptor,写请求和读响应拦截器


Response intercept(Chain chain) throws IOException {
    RealInterceptorChain realChain = (RealInterceptorChain) chain;
    Exchange exchange = realChain.exchange();
    Request request = realChain.request();
    //写请求头
    exchange.writeRequestHeaders(request);
    Response.Builder responseBuilder = null;
    //处理请求体body...
    //读取响应头
    responseBuilder = exchange.readResponseHeaders(false);
    //构建响应
    Response response = responseBuilder
        .request(request)
        .handshake(exchange.connection().handshake())
        .sentRequestAtMillis(sentRequestMillis)
        .receivedResponseAtMillis(System.currentTimeMillis())
        .build();
    //读取响应体
    response = response.newBuilder()
        .body(exchange.openResponseBody(response))
        .build();
    return response;
}

拦截器准备好后,通过拦截器集合创建RealInterceptorChain拦截器链对象。

RealInterceptorChain实现了Interceptor.Chain接口,添加的每个拦截器实现了Intercepter接口。

最终调用拦截器链调用proceed函数。Response response = chain.proceed(originalRequest);

public Response proceed(Request request, Transmitter transmitter, @Nullable Exchange exchange)
      throws IOException {
    if (index >= interceptors.size()) throw new AssertionError();

    calls++;

    // If we already have a stream, confirm that the incoming request will use it.
    if (this.exchange != null && !this.exchange.connection().supportsUrl(request.url())) {
      throw new IllegalStateException("network interceptor " + interceptors.get(index - 1)
          + " must retain the same host and port");
    }

    // If we already have a stream, confirm that this is the only call to chain.proceed().
    if (this.exchange != null && calls > 1) {
      throw new IllegalStateException("network interceptor " + interceptors.get(index - 1)
          + " must call proceed() exactly once");
    }

    // Call the next interceptor in the chain.
    RealInterceptorChain next = new RealInterceptorChain(interceptors, transmitter, exchange,
        index + 1, request, call, connectTimeout, readTimeout, writeTimeout);
    Interceptor interceptor = interceptors.get(index);
    Response response = interceptor.intercept(next);

    // Confirm that the next interceptor made its required call to chain.proceed().
    if (exchange != null && index + 1 < interceptors.size() && next.calls != 1) {
      throw new IllegalStateException("network interceptor " + interceptor
          + " must call proceed() exactly once");
    }

    // Confirm that the intercepted response isn't null.
    if (response == null) {
      throw new NullPointerException("interceptor " + interceptor + " returned null");
    }

    if (response.body() == null) {
      throw new IllegalStateException(
          "interceptor " + interceptor + " returned a response with no body");
    }

    return response;
  }
众所周知的责任链模式。首先创建新的RealInterceptorChain对象,每次传入的index都会增加,获取到当前的拦截器,调用拦截器的intercept函数,每个拦截器的intercept函数前面已经列出来了。拦截器都会先对Request进行处理,然后index+1传到下一个拦截器,最终CallServerInterceptor拿到response对响应进行一些响应码的处理后再一层一层的向上一个拦截器返回response,拦截器链上的每个拦截器节点再顺序的对reponse进行处理。拦截器对request和response的处理是逆序的。

 

关于Transmitter,ExChange,RealConnection的理解还是很模糊。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值