美文网首页android
Okhttp的责任链模式和拦截器分析

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

作者: Android程序员老鸦 | 来源:发表于2021-06-21 16:49 被阅读0次

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再逐层往上传递直到开发者的回调接口。

相关文章

  • okhttp和责任链模式

    OkHttp—拦截器这篇文章讲了拦截器,今天就谈谈责任链模式责任链模式,其实就是把request通过一系列Inte...

  • Okhttp之RetryAndFollowUpIntercept

    如果研究过okhttp源码,应该知道okhttp的核心是拦截器,而拦截器所采用的设计模式是责任链设计,即每个拦截器...

  • Okhttp之BridgeInterceptor拦截器解析

    如果研究过okhttp源码,应该知道okhttp的核心是拦截器,而拦截器所采用的设计模式是责任链设计,即每个拦截器...

  • Android OkHttp拦截器源码分析一--简介

    拦截器OkHttp强大功能 拦截器使用了责任链设计模式,Okhttp源码中拦截器共有五个 在拦截器中我们可以做自定...

  • Mybatis系列之七 Interceptor

    一、思路 责任链模式小例子源码分析 二、责任链模式 Mybatis拦截器采用了责任链模式。这里简单讲一下责任链模式...

  • 责任链模式

    概念   说到责任链模式,我就想起了okHttp中设置拦截器的时候了,今年、中外、开花,关注。  其实责任链就是将...

  • okhttp拦截器-责任链模式

    okhttp拦截器采用责任链的设计模式,内置五层拦截器,并提供两种拦截器供用户插入链,类似压栈的结构,后进先出,最...

  • 高仿okhttp手写责任链模式

    okhttp使用的设计模式面试的时候经常被问到,其中里面最多的建造者模式和责任链模式其中责任链模式也是okhttp...

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

    Okhttp的浅层架构分析[https://www.jianshu.com/p/4f1cd0a6e1be]Okht...

  • OkHttp源码之RetryAndFollowUpInterce

    之前在上一篇文章okhttp源码之责任链模式中有提到过,okhttp的所有功能都是通过拦截器来实现的,就是我们今天...

网友评论

    本文标题:Okhttp的责任链模式和拦截器分析

    本文链接:https://www.haomeiwen.com/subject/okgsyltx.html