okhttp源码阅读-同步请求实现(二)

同步请求看完了,看了大概两天。看的过程中我也有很多疑惑,看完之后感觉很明朗。

疑惑有一下三点

1.请求加入了同步队列,为什么没有从队列中取出请求去请求网络,放入队列的作用是什么?

2.RealInterceptorChain类中的proceed()方法调用Interceptor实现类中的intercept(next)方法接着Interceptor实现类中的intercept()方法调用RealInterceptorChain类的proceed()方法。A调B,B调A,然后。。。。。 难道就这样调用下去吗,什么时候结束呢?

先回答问题吧---------

对于第一个放入同步队列中什么事也没干,请求完成后又移除了。

对于第二个去翻资料说是责任链模式,这个也是okhttp设计的核心吧。

好吧咱们一起看同步请求的源码

OkHttpClient client = new OkHttpClient();

    Request request = new Request.Builder()
            .url("https://api.github.com/repos/square/okhttp/issues")
            .header("User-Agent", "OkHttp Headers.java")
            .addHeader("Accept", "application/json; q=0.5")
            .addHeader("Accept", "application/vnd.github.v3+json")
            .build();
Response response = null;
try {
    response = client.newCall(request).execute();
    if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
    System.out.println("Server: " + response.header("Server"));
    System.out.println("Date: " + response.header("Date"));
    System.out.println("Vary: " + response.headers("Vary"));
} catch (IOException e) {
    e.printStackTrace();
}

接下来咱们分析response = client.newCall(request).execute();

看newCall( )方法返回的是什么

@Override public Call newCall(Request request) {
  return new RealCall(this, request, false /* for web socket */);
}
通过以上代码看到返回的是RealCall类的对象,咱们再看RealCall类的execute方法。
@Override public Response execute() throws IOException {
  synchronized (this) {
    if (executed) throw new IllegalStateException("Already Executed");
    executed = true;
  }
  captureCallStackTrace();
  try {
    client.dispatcher().executed(this);
    Response result = getResponseWithInterceptorChain();
    if (result == null) throw new IOException("Canceled");
    return result;
  } finally {
    client.dispatcher().finished(this);
  }
}

划线部分是核心代码

第一行说的是放入队列

第二行是责任链的开始

第三行是从队列中移除

咱们重点说一下第二行,找到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);
  return chain.proceed(originalRequest);
}

接下来咱们跟进到RealInterceptorChain中的proceed方法。

@Override public Response proceed(Request request) throws IOException {
  return proceed(request, streamAllocation, httpCodec, connection);
}

接着跟进

public Response proceed(Request request, StreamAllocation streamAllocation, HttpCodec httpCodec,
    RealConnection connection) throws IOException {
  if (index >= interceptors.size()) throw new AssertionError();

  calls++;

  // Call the next interceptor in the chain.//请求下一个拦截器,说的是下面整块代码


//实例话RealInterceptorChain对象,注意:此时此对象的index已经实现了加1,再提醒一下proceed方法就是在  RealInterceptorChain类中
  RealInterceptorChain next = new RealInterceptorChain(
      interceptors, streamAllocation, httpCodec, connection, index + 1, request);  
  Interceptor interceptor = interceptors.get(index); //根据index,从拦截器集合中获取拦截器
  Response response = interceptor.intercept(next); //调用当前拦截器的拦截方法,并把RealInterceptorChain对象传递  下去
  return response;
}

Interceptor是一个接口,实现这个接口的类有很多,有多少呢?回过头去看一下标红色的代码,装入拦截器集合的全是Interceptor的实现类。所以咱们找两个说一下责任链,一个是ConnectInterceptor另一个是最后的拦截器CallServerInterceptor

看一下ConnectInterceptor类中intercept(next)方法如下,我在代码后面注释说明吧

@Override public Response intercept(Chain chain) throws IOException {
  RealInterceptorChain realChain = (RealInterceptorChain) chain;  //强转没什么好解释的
  Request request = realChain.request(); //得到请求
  StreamAllocation streamAllocation = realChain.streamAllocation();

  // We need the network to satisfy this request. Possibly for validating a conditional GET.
  boolean doExtensiveHealthChecks = !request.method().equals("GET");
  HttpCodec httpCodec = streamAllocation.newStream(client, doExtensiveHealthChecks);
  RealConnection connection = streamAllocation.connection(); //和服务器建立连接

  return realChain.proceed(request, streamAllocation, httpCodec, connection); //调用RealInterceptorChain类的proceed()方法,此时index已经为1了。好了咱们再看proceed方法,同样会执行划线部分的代码实例话下一个RealInterceptorChain对象,得到index为1的拦截器,调用该拦截器的拦截方法。等到下一个拦截器的时候同样再调用RealInterceptorChain类的proceed方法,依次类推知道遍历到最后一个拦截器,那么最后一个拦截器是谁呢?是最后一个加入拦截器集合中的拦截器,从红色代码出可以看出就是CallServerInterceptor拦截器。好了咱们看看一下这个拦截器的拦截方法干了什么

因为代码太多我在代码后面注释说明

@Override public Response intercept(Chain chain) throws IOException {
  RealInterceptorChain realChain = (RealInterceptorChain) chain;
  HttpCodec httpCodec = realChain.httpStream();
  StreamAllocation streamAllocation = realChain.streamAllocation();
  RealConnection connection = (RealConnection) realChain.connection(); //得到之前已经建立的连接
  Request request = realChain.request();  //得到要请求的的内容

  long sentRequestMillis = System.currentTimeMillis();
  httpCodec.writeRequestHeaders(request);  //向服务器发送要发送给服务器的内容

  Response.Builder responseBuilder = null;
  if (HttpMethod.permitsRequestBody(request.method()) && request.body() != null) {
    // If there's a "Expect: 100-continue" header on the request, wait for a "HTTP/1.1 100
    // Continue" response before transmitting the request body. If we don't get that, return what
    // we did get (such as a 4xx response) without ever transmitting the request body.
    if ("100-continue".equalsIgnoreCase(request.header("Expect"))) {
      httpCodec.flushRequest();
      responseBuilder = httpCodec.readResponseHeaders(true);
    }

    if (responseBuilder == null) {
      // Write the request body if the "Expect: 100-continue" expectation was met.
      Sink requestBodyOut = httpCodec.createRequestBody(request, request.body().contentLength());
      BufferedSink bufferedRequestBody = Okio.buffer(requestBodyOut);
      request.body().writeTo(bufferedRequestBody);
      bufferedRequestBody.close();
    } else if (!connection.isMultiplexed()) {
      // If the "Expect: 100-continue" expectation wasn't met, prevent the HTTP/1 connection from
      // being reused. Otherwise we're still obligated to transmit the request body to leave the
      // connection in a consistent state.
      streamAllocation.noNewStreams();
    }
  }

  httpCodec.finishRequest(); //发送完成

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

  Response response = responseBuilder
      .request(request)
      .handshake(streamAllocation.connection().handshake())
      .sentRequestAtMillis(sentRequestMillis)
      .receivedResponseAtMillis(System.currentTimeMillis())
      .build(); //得到response

  int code = response.code();
  if (forWebSocket && code == 101) {
    // Connection is upgrading, but we need to ensure interceptors see a non-null response body.
    response = response.newBuilder()
        .body(Util.EMPTY_RESPONSE)
        .build();
  } else {
    response = response.newBuilder()
        .body(httpCodec.openResponseBody(response))
        .build();
  }

  if ("close".equalsIgnoreCase(response.request().header("Connection"))
      || "close".equalsIgnoreCase(response.header("Connection"))) {
    streamAllocation.noNewStreams();
  }

  if ((code == 204 || code == 205) && response.body().contentLength() > 0) {
    throw new ProtocolException(
        "HTTP " + code + " had non-zero Content-Length: " + response.body().contentLength());
  }

  return response;
}

好了同步请求就到这了,下面我将读一下异步请求的代码。

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值