OkHttp的Interceptor原理分析
OkHttp的Interceptor原理分析
林泳坛 发表于2年前
OkHttp的Interceptor原理分析
  • 发表于 2年前
  • 阅读 533
  • 收藏 1
  • 点赞 1
  • 评论 0

腾讯云实验室 1小时搭建人工智能应用,让技术更容易入门 免费体验 >>>   

摘要: 这里用到了责任链模式,这种模式在JavaWeb中的filter,和Strust2中的Interceptor得到充分的体现。

OkHttp的Interceptor原理分析

标签(空格分隔): Java OkHttp Interceptor Chain


样例

OkHttpClient mClient = new OkHttpClient();
CookieManager cookieManager = new CookieManager(new PersistentCookieStore(BaseApplication.instance()), CookiePolicy.ACCEPT_ALL);
mClient.setCookieHandler(cookieManager);
mClient.interceptors().add(chain -> {
    Request originReq = chain.request();
    HttpUrl httpUrl = originReq.httpUrl().newBuilder().addQueryParameter("auth_token", BaseApplication.instance().getToken()).build();
    Request.Builder reqBuilder = originReq.newBuilder();
    reqBuilder.header("mobile_platform", "android").url(httpUrl);
    Request req = reqBuilder.build();
    Response resp = chain.proceed(req);
    if (Settings.isDebug) {
    }
    return resp;
});
if (Settings.isDebug) {
    HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
    logging.setLevel(HttpLoggingInterceptor.Level.BODY);
    mClient.interceptors().add(logging);
}

上面代码中,我已经向mClient中添加了两个拦截器。第一个用于给原来的请求添加一个auth_token查询参数,第二个用于在请求前后把请求的内容和响应的内容打出来到控制台中。

入口

首先,得把OkHttp的源码git下来,然后找到OkHttpClient类,再找到其中的newCall(request)方法。好,故事从这里开始。代码如下,

  /**
   * Prepares the {@code request} to be executed at some point in the future.
   */
  public Call newCall(Request request) {
    return new Call(this, request);
  }

很简单,就是直接新建一个Call对象而已,所以关键不是这里,而是Call类。我们拿到Call对象之后一般是调用enqueue方法或者execute方法。我们就拿比较简单的execute方法来做切入点。对应的代码如下,

  public Response execute() throws IOException {
  
    ··· 这里省略了若干行代码
    
    try {
      client.getDispatcher().executed(this);
      Response result = getResponseWithInterceptorChain(false);
      if (result == null) throw new IOException("Canceled");
      return result;
    } finally {
      client.getDispatcher().finished(this);
    }
  }

上面代码中,关键在于getResponseWithInterceptorChain方法。最后我们的结果也就是从这个方法中产生的,代码如下,

  private Response getResponseWithInterceptorChain(boolean forWebSocket) throws IOException {
    Interceptor.Chain chain = new ApplicationInterceptorChain(0, originalRequest, forWebSocket);
    return chain.proceed(originalRequest);
  }

  class ApplicationInterceptorChain implements Interceptor.Chain {
    private final int index;
    private final Request request;
    private final boolean forWebSocket;

    ApplicationInterceptorChain(int index, Request request, boolean forWebSocket) {
      this.index = index;
      this.request = request;
      this.forWebSocket = forWebSocket;
    }

    ··· 这里省略了若干行代码

    @Override public Response proceed(Request request) throws IOException {
      // If there's another interceptor in the chain, call that.
      if (index < client.interceptors().size()) {
        Interceptor.Chain chain = new ApplicationInterceptorChain(index + 1, request, forWebSocket);
        Interceptor interceptor = client.interceptors().get(index);
        Response interceptedResponse = interceptor.intercept(chain);

        ··· 这里省略了若干行代码

        return interceptedResponse;
      }

      // No more interceptors. Do HTTP.
      return getResponse(request, forWebSocket);
    }
  }

从上面代码中,我们看到有一个ApplicationInterceptorChain这个种东西参与其中。这个东西是责任链设计模式的关键——链,它把多个处理器(对应这里的Interceptor)串联在一起,并且请求会在条链上传递下去,直到找到真正有责任处理这个请求的处理器(即这里的Interceptor)。上面代码中,我们可以看出,处理请求的责任落在了最后一个处理器上。

代码是最好的文档,我们看它的类定义。它实现了Chain接口,就是我们向OkHttpClient中添加Interceptor时接收到的参数。它的作用是记录当前Intercepter的索引(index)和Request对象,并且请求index对应的拦截器获取结果,并且把下链条的下一截作为参数传给拦截器。拦截器收到chain参数后,最终还是要调用chain的proceed方法。所以,这里就是一个递归过程,一直到最后一个拦截器,才真正的进入到OkHttp的网络请求核心获取数据。获取到数据之后,Response就会在拦截器中逆向传递。

声名

By 啪嗒科技 AtanL(atanl@padakeji.com)

©啪嗒科技版本所有,没有经作者允许,只能发表于padakeji.com相关域名下。

共有 人打赏支持
粉丝 4
博文 18
码字总数 13321
×
林泳坛
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: