Okhttp的责任链模式和拦截器分析

Okhttp的浅层架构分析
Okhttp的责任链模式和拦截器分析
Okhttp之RetryAndFollowUpInterceptor拦截器分析
Okhttp之BridgeInterceptor拦截器分析
Okhttp之CacheInterceptor拦截器分析
Okhttp之ConnectInterceptor拦截器分析
Okhttp之网络连接相关三大类RealConnection、ConnectionPool、StreamAllocation
上篇大概梳理了一下okhttp的线程调用流程,这次接着看看它真正的网络请求步骤,也就是责任链模式和拦截器相关的知识。接着上篇的终点:

  //最终的请求提交,可以看到getResponseWithInterceptorChain()方法拿到response ,这就是开始了责任链调用模式,后面详细分析
    @Override
   protected void execute() {
      boolean signalledCallback = false;
      timeout.enter();
      try {
      //开启责任链调用
        Response response = getResponseWithInterceptorChain();
        if (retryAndFollowUpInterceptor.isCanceled()) {
          signalledCallback = true;
         //取消了请求,调用回调接口的onFailure()方法
          responseCallback.onFailure(RealCall.this, new IOException("Canceled"));
        } else {
          signalledCallback = true;
          //拿到了response数据,调用回调接口的onResponse()方法
          responseCallback.onResponse(RealCall.this, response);
        }
      } catch (IOException e) {
        e = timeoutExit(e);
        if (signalledCallback) {
          // Do not signal the callback twice!
          Platform.get().log(INFO, "Callback failure for " + toLoggableString(), e);
        } else {
          eventListener.callFailed(RealCall.this, e);
          responseCallback.onFailure(RealCall.this, e);
        }
      } 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));//负责链接网络,socket相关
    if (!forWebSocket) {
      interceptors.addAll(client.networkInterceptors());//对响应体进行第一时间处理,开发者自定义
    }
    interceptors.add(new CallServerInterceptor(forWebSocket));//负责读写数据
    //将所有要用到的拦截器封装在这个新建的RealInterceptorChain里面
    Interceptor.Chain chain = new RealInterceptorChain(interceptors, null, null, null, 0,
        originalRequest, this, eventListener, client.connectTimeoutMillis(),
        client.readTimeoutMillis(), client.writeTimeoutMillis());
    //并调用它的proceed()方法,开启责任链调用,这个方法会把每个拦截器的process执行一遍,层层传递下去
    return chain.proceed(originalRequest);
  }

我们先来研究它的责任链是怎么串起来的,先看看Interceptor接口:

//Interceptor 接口,所有的拦截器都要实现它,并重写intercept(Chain chain)方法
public interface Interceptor {
  //就是靠着这个方法一个一个拦截器传递下去
  Response intercept(Chain chain) throws IOException;
  //内部接口,意义如其名,链条,起到连接每个拦截器 的作用
  interface Chain {
    Request request();

    Response proceed(Request request) throws IOException;
    ...省略无关代码
  }
}

再看看Chain 的实现类RealInterceptorChain:

public final class RealInterceptorChain implements Interceptor.Chain {
  private final List<Interceptor> interceptors;//所有的拦截器集合
  private final StreamAllocation streamAllocation;
  private final HttpCodec httpCodec;
  private final RealConnection connection;
  private final int index;//当前的拦截器下标
  private final Request request;//请求
  private final Call call;
  private final EventListener eventListener;
  private final int connectTimeout;
  private final int readTimeout;
  private final int writeTimeout;
  private int calls;
  
 @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 {
    calls++;
    // 又new了一个RealInterceptorChain ,index +1,而且把所有的数据都传给它
    RealInterceptorChain next = new RealInterceptorChain(interceptors, streamAllocation, httpCodec,
        connection, index + 1, request, call, eventListener, connectTimeout, readTimeout,
        writeTimeout);
    //取出当前的拦截器,即第一个拦截器
    Interceptor interceptor = interceptors.get(index);
    //调用他的intercept()方法,并把刚刚创建的RealInterceptorChain 传给它
    Response response = interceptor.intercept(next);

    ...省略旁支代码
    return response;
  }
}

现在我们来看看官方的第一个拦截器retryAndFollowUpInterceptor干了什么,以及他是怎么把下一个拦截器调动起来的,这里重点分析责任链的流转机制,不对拦截器具体功能分析:

public final class RetryAndFollowUpInterceptor implements Interceptor {
  /**
   * How many redirects and auth challenges should we attempt? Chrome follows 21 redirects; Firefox,
   * curl, and wget follow 20; Safari follows 16; and HTTP/1.0 recommends 5.
   */
  private static final int MAX_FOLLOW_UPS = 20;

  private final OkHttpClient client;
  private final boolean forWebSocket;
  private volatile StreamAllocation streamAllocation;
  private Object callStackTrace;
  private volatile boolean canceled;

  @Override public Response intercept(Chain chain) throws IOException {
    //从chain里拿到request
    Request request = chain.request();
    //强转成RealInterceptorChain 
    RealInterceptorChain realChain = (RealInterceptorChain) chain;
   
    while (true) {
     ...省略
        //看到了调用了realChain的proceed() 
        response = realChain.proceed(request, streamAllocation, null, null);
    ...省略
    }
}

看到RetryAndFollowUpInterceptor的intercept(Chain chain) 方法就是拿出request进行处理,然后继续调用RealInterceptorChain 的proceed()方法,这个方法在上面分析过了,它会new一个新的RealInterceptorChain 然后拿出下一个拦截器执行它的intercept(Chain chain)方法,就这样一直传递到最后的CallServerInterceptor拦截器,这个拦截器最终会返回一个response,然后顺着之前的拦截器再把这个response往上传,从而让整个责任链都串联起来,而链条正是RealInterceptorChain。
用图来描述一下:


责任链模式.png
可以看到每个interceptor之间都有一个RealInterceptorChain,从左边开启责任链request经过每一个拦截器的加工直到CallServerInterceptor返回response再逐层往上传递直到开发者的回调接口。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容