文档章节

OkHttp的Interceptor原理分析

林泳坛
 林泳坛
发布于 2016/03/03 13:48
字数 841
阅读 586
收藏 1
点赞 1
评论 0

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相关域名下。

© 著作权归作者所有

共有 人打赏支持
林泳坛
粉丝 3
博文 18
码字总数 13321
作品 0
广州
程序员
Android面试的那些答不上来的问题(一)--- OkHttp的拦截器你到底了解多少(上)

前言 前段时间面试了很多家公司(坐标成都,大大小小加起来得20家吧),有时候有些事做多了,你就会发现它的一些窍门或者规律,面试这件事当然也不例外。其实很多公司问到的问题都大同小异,...

SillyMonkey ⋅ 05/10 ⋅ 0

Android面试有迹可循(一)OkHttp3.9拦截器原理与区别

接上回 传送门 上回我们讲到,OkHttp的请求过程中有个非常重要的东西-“拦截器”,而且拦截器又分为interceptors和networkInterceptors两种,那它们具体有何区别呢?又要怎么来使用?现在来一...

SillyMonkey ⋅ 05/19 ⋅ 0

spring传统xml配置okhttp3

问题 后端服务需要使用http客户端请求其他服务支持,项目中需要将HttpClient换成OKhttp,为啥要换OKhttp?这里不讨论这两者之间的优缺点。这篇文章主要关注与Spring传统xml配置方式集成Okhtt...

亚林瓜子 ⋅ 04/19 ⋅ 0

Android逆向之旅---爆破一款资讯类应用「最右」防抓包策略原理分析

一、逆向分析 首先感谢王同学提供的样本,因为王同学那天找到我咨询我说有一个应用Fiddler抓包失败,其实对于这类问题,我一般都会这么回答:第一你是否安装Fiddler证书了,他说他安装了。第...

jiangwei0910410003 ⋅ 04/25 ⋅ 0

Retrofit源码分析之OKHttpCall

之前在Retrofit源码初探一文中我们提出了三个问题: 什么时候开始将注解中参数拼装成http请求的信息的? 如何产生发起http请求对象的? 如何将对象转换成我们在接口中指定的返回值的? 其中第...

低情商的大仙 ⋅ 05/13 ⋅ 0

说说在 Android 中如何发送 HTTP 请求

客户端会向服务器发出一条 HTTP 请求,服务器收到请求后会返回一些数据给客户端,然后客户端再对这些数据进行解析与处理。 1 HttpURLConnection 可以使用 HttpURLConnection(官方推荐) 来发...

deniro ⋅ 06/09 ⋅ 0

OkHttp源码学习系列一:总流程和Dispatcher分析

本文为本人原创,转载请注明作者和出处。 OkHttp可以说是目前Android开发中最流行的基础网络框架了。相信你也一定早已学会了它的基本用法,今天我们来进一步学习它的源码,了解其请求原理,学...

业松 ⋅ 05/10 ⋅ 0

BAT大厂APP架构演进实践与优化之路

第1章 打车课程项目整体介绍 课程介绍:介绍课程内容、教授方式,讲诉打车业务的整体架构思路;针对打车业务如何进行需求分析和工作量化评估,同时根据工作量化提出课程内容章节计划。 第2章...

13269051240 ⋅ 05/21 ⋅ 0

OkHttp3源码解析内部缓存

OkHttp3系列文章 OkHttp3 源码解析执行流程 OkHttp3 源码解析 连接池的复用 如果有了解过OkHttp的执行流程,可以知道,在拦截器链中有一个缓存拦截器CacheInterceptor,里面决定了是由缓存中...

Gillben ⋅ 05/22 ⋅ 0

[Tools] [okHttp] 调试笔记 --- 无法找到FormEncodingBuilder类

背景: 网上很多例子在讲okHttp的post和get时会用FormEncodingBuilder来构建RequstBody。 但是在okHttp3上,此接口已经已经变掉了,替代它的是MultipartBuilder。 官方说明: okHttp3所有改动...

kris_fei ⋅ 05/25 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

Mahout推荐算法之SlopOne

一、 算法原理 有别于基于用户的协同过滤和基于item的协同过滤,SlopeOne采用简单的线性模型估计用户对item的评分。如下图,估计UserB对ItemJ的偏好 图(1) 在真实情况下,该方法有如下几个...

xiaomin0322 ⋅ 4分钟前 ⋅ 0

LVM讲解

LVM是什么 LVM是 Logical Volume Manager(逻辑卷管理)的简写,它是Linux环境下对磁盘分区进行管理的一种机制,Linux用户安装Linux操作系统时遇到的一个常见的难以决定的问题就是如何正确地...

李超小牛子 ⋅ 13分钟前 ⋅ 0

mysql更改密码、连接mysql、mysql常用命令

1. 更改mysql的root账户密码: mysql中root账户和系统root不是一个账户 1.1 更改环境变量PATH,增加mysql绝对路径 由于mysql安装目录为/usr/local/mysql/,所以系统不能直接使用mysql,需把/...

laoba ⋅ 15分钟前 ⋅ 0

阿里云发布企业数字化及上云外包平台服务:阿里云众包平台

摘要: 阿里云正式发布旗下众包平台业务(网址:https://zhongbao.aliyun.com/),支持包括:网站定制开发,APP、电商系统等软件开发,商标、商品LOGO、VI、产品包装设计、营销推广、大数据人...

猫耳m ⋅ 15分钟前 ⋅ 0

阿里云发布企业数字化及上云外包平台服务:阿里云众包平台

摘要: 阿里云正式发布旗下众包平台业务(网址:https://zhongbao.aliyun.com/),支持包括:网站定制开发,APP、电商系统等软件开发,商标、商品LOGO、VI、产品包装设计、营销推广、大数据人...

阿里云云栖社区 ⋅ 18分钟前 ⋅ 0

1.03-Maven中使用ueditor富文本编辑器

起因:在maven仓库未找到百度的ueditor的jar包 操作: 1.下载百度的ueditor的jar包 2.打开命令行,切换到ueditor的下载位置,运行一下命令: mvn install:install-file -Dfile=ueditor-1.1....

静以修身2025 ⋅ 24分钟前 ⋅ 0

几道Spring 面试题

1、BeanFactory 接口和 ApplicationContext 接口有什么区别? ApplicationContext 接口继承BeanFactory接口 Spring核心工厂是BeanFactory BeanFactory采取延迟加载,第一次getBean时才会初始...

职业搬砖20年 ⋅ 33分钟前 ⋅ 0

包饺子

http://storage.slide.news.sina.com.cn/slidenews/77_ori/2018_24/74766_826131_625489.gif

霜叶情 ⋅ 34分钟前 ⋅ 0

xml解析

方法一: String s_xml1 = "<xml>" + "<head>lalalalal</head>" + "<body>1234</body>" + "</xml>"; try { DocumentBuilderFactory documentBuilderFactory......

GithubXD ⋅ 46分钟前 ⋅ 0

reuse stream

Although Java streams were designed to be operated only once, programmers still ask how to reuse a stream. From a simple web search, we can find many posts with this same issue ......

idoz ⋅ 47分钟前 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部