OkHttp3源码详解(三) 拦截器

简介: 阿里P7移动互联网架构师进阶视频(每日更新中)免费学习请点击:https://space.bilibili.com/4743806801.构造Demo 首先构造一个简单的异步网络访问Demo: 1. OkHttpClient client = new OkHttpClient(); 2.

首先构造一个简单的异步网络访问Demo:

1.  OkHttpClient client =  new  OkHttpClient();
2.  Request request =  new  Request.Builder()
3.  .url("http://publicobject.com/helloworld.txt")
4.  .build();

6.  client.newCall(request).enqueue(new  Callback()  {
7.  @Override
8.  public  void onFailure(Call call,  IOException e)  {
9.  Log.d("OkHttp",  "Call Failed:"  + e.getMessage());
10.  }

12.  @Override
13.  public  void onResponse(Call call,  Response response)  throws  IOException  {
14.  Log.d("OkHttp",  "Call succeeded:"  + response.message());
15.  }
16.  });

2. 发起请求

OkHttpClient.newCall实际是创建一个RealCall实例:

1.  @Override
2.  public  Call newCall(Request request)  {
3.  return  new  RealCall(this, request,  false  /* for web socket */);
4.  }

RealCall.enqueue实际就是讲一个RealCall放入到任务队列中,等待合适的机会执行:

1.  @Override
2.  public  void enqueue(Callback responseCallback)  {
3.  synchronized  (this)  {
4.  if  (executed)  throw  new  IllegalStateException("Already Executed");
5.  executed =  true;
6.  }
7.  captureCallStackTrace();
8.  client.dispatcher().enqueue(new  AsyncCall(responseCallback));
9.  }

从代码中可以看到最终RealCall被转化成一个AsyncCall并被放入到任务队列中,任务队列中的分发逻辑这里先不说,相关实现会放在OkHttp源码分析——任务队列疑问进行介绍。这里只需要知道AsyncCall的excute方法最终将会被执行:

1.  [RealCall.java]
2.  @Override  protected  void execute()  {
3.  boolean signalledCallback =  false;
4.  try  {
5.  Response response = getResponseWithInterceptorChain();
6.  if  (retryAndFollowUpInterceptor.isCanceled())  {
7.  signalledCallback =  true;
8.  responseCallback.onFailure(RealCall.this,  new  IOException("Canceled"));
9.  }  else  {
10.  signalledCallback =  true;
11.  responseCallback.onResponse(RealCall.this, response);
12.  }
13.  }  catch  (IOException e)  {
14.  if  (signalledCallback)  {
15.  // Do not signal the callback twice!
16.  Platform.get().log(INFO,  "Callback failure for "  + toLoggableString(), e);
17.  }  else  {
18.  responseCallback.onFailure(RealCall.this, e);
19.  }
20.  }  finally  {
21.  client.dispatcher().finished(this);
22.  }
23.  }
24.  }

execute方法的逻辑并不复杂,简单的说就是:

调用getResponseWithInterceptorChain获取服务器返回
通知任务分发器(client.dispatcher)该任务已结束
getResponseWithInterceptorChain构建了一个拦截器链,通过依次执行该拦截器链中的每一个拦截器最终得到服务器返回。

3. 构建拦截器链
首先来看下getResponseWithInterceptorChain的实现:

源码路径:okhttp3/RealCall.java

 // 开始执行整个请求
 Response getResponseWithInterceptorChain() throws IOException {
   // Build a full stack of interceptors.
   // 拦截器栈
   List<Interceptor> interceptors = new ArrayList<>();
   // 前文说过的 普通拦截器
   interceptors.addAll(client.interceptors());
   // 重试拦截器,网络错误、请求失败等
   interceptors.add(retryAndFollowUpInterceptor);
   // 桥接拦截器,主要是重构请求头即header
   interceptors.add(new BridgeInterceptor(client.cookieJar()));
   // 缓存拦截器
   interceptors.add(newCacheInterceptor(client.internalCache()));
   // 连接拦截器,连接服务器,https包装
   interceptors.add(new ConnectInterceptor(client));
   // 网络拦截器,websockt不支持,同样是自定义
   if (!forWebSocket) {
     interceptors.addAll(client.networkInterceptors());
   }
   // 服务拦截器,主要是发送(write、input)、读取(read、output)数据
   interceptors.add(new CallServerInterceptor(forWebSocket));

   // 开启调用链
   Interceptor.Chain chain = new RealInterceptorChain(
       interceptors, , originalRequest);
   return chain.proceed(originalRequest);
 }

其逻辑大致分为两部分:

创建一系列拦截器,并将其放入一个拦截器数组中。这部分拦截器即包括用户自定义的拦截器也包括框架内部拦截器
创建一个拦截器链RealInterceptorChain,并执行拦截器链的proceed方法
接下来看下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 int calls;

   public RealInterceptorChain(List<Interceptor> interceptors, StreamAllocation streamAllocation,
                               HttpCodec httpCodec, RealConnection connection, int index, Request request) {
     this.interceptors = interceptors;
     this.connection = connection;
     this.streamAllocation = streamAllocation;
     this.httpCodec = httpCodec;
     this.index = index;
     this.request = request;
   }

   @Override public Connection connection() {
     return connection;
   }

   public StreamAllocation streamAllocation() {
     return streamAllocation;
   }

   public HttpCodec httpStream() {
     return httpCodec;
   }

   @Override public Request request() {
     return request;
   }

   @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 {

     ......
     // Call the next interceptor in the chain.
     RealInterceptorChain next = new RealInterceptorChain(
         interceptors, streamAllocation, httpCodec, connection, index + , request);
     Interceptor interceptor = interceptors.get(index);
     Response response = interceptor.intercept(next);

     ...... 

     return response;
   }
 }

在proceed方法中的核心代码可以看到,proceed实际上也做了两件事:

创建下一个拦截链。传入index + 1使得下一个拦截器链只能从下一个拦截器开始访问
执行索引为index的intercept方法,并将下一个拦截器链传入该方法。
原文链接:https://www.bbsmax.com/A/MAzAEmQMz9/

相关文章
|
6月前
|
缓存
okhttp Interceptor
okhttp Interceptor
63 1
|
监控 Java Spring
gRPC中interceptor拦截器的总结和实践
gRPC中的interceptor拦截器分为客户端拦截器和服务端拦截器,分别是在客户端和服务端的请求被发送出去之前进行处理的逻辑。常见的使用场景有:(1)请求日志记录及监控;(2)添加请求头数据、以便代理转发使用;(3)请求或者结果重写。
480 0
gRPC中interceptor拦截器的总结和实践
|
存储 中间件 测试技术
gRPC(六)进阶:拦截器 interceptor
拦截器本质上就是一个特定类型的函数,所以实现拦截器只需要实现对应类型方法(方法签名相同)即可。
920 1
gRPC(六)进阶:拦截器 interceptor
|
设计模式 缓存 监控
OKHttp3 从使用到原理分析
Okhttp3 是我们经常使用的一个网络框架,可扩展性强,支持 get 缓存, spdy、http2.0,gzip 压缩减少数据流量,同步和异步请求,连接池复用机制等特性让广大 android 开发者深爱不已,今天我就带大家从 Okhttp 简单使用,到各种好用拦截器原理了解 Okhttp3
1794 0
OKHttp3 从使用到原理分析
|
存储 缓存 网络协议
源码阅读 | Okhttp
源码阅读 | Okhttp
|
JSON Android开发 数据格式
RxJava+Retrofit示例 ,Retrofit 注解学习
RxJava+Retrofit示例 ,Retrofit 注解学习
167 0
|
缓存 JSON 数据格式
OkHttp3源码详解(一) Request类
阿里P7移动互联网架构师进阶视频(每日更新中)免费学习请点击:https://space.bilibili.com/474380680每一次网络请求都是一个Request,Request是对url,method,header,body的封装,也是对Http协议中请求行,请求头,实体内容的封装 p.
|
存储 Android开发
OkHttp源码详解之Okio源码详解
OkHttp源码详解之Okio源码详解
OkHttp源码详解之Okio源码详解
|
设计模式 Java API
【OkHttp】OkHttp 源码分析 ( 网络框架封装 | OkHttp 4 迁移 | OkHttp 建造者模式 )
【OkHttp】OkHttp 源码分析 ( 网络框架封装 | OkHttp 4 迁移 | OkHttp 建造者模式 )
347 0
【OkHttp】OkHttp 源码分析 ( 网络框架封装 | OkHttp 4 迁移 | OkHttp 建造者模式 )
|
前端开发
jfinal拦截器Interceptor解析
jfinal拦截器Interceptor解析
310 0
jfinal拦截器Interceptor解析