OKHTTP系列(三)--拦截器Interceptor概述

本文回顾了OKHTTP请求处理流程,介绍了拦截器调用顺序。详细解释了Okhttp内置拦截器,如RetryAndFollowUpInterceptor负责失败重试与重定向,BridgeInterceptor负责请求与响应转换等。还说明了Request正向处理、Response逆向处理,参考了OSI七层模型原理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

回顾

我们先回顾先我们OKHTTP系列(二)--请求与响应流程中的请求的处理:

final class RealCall implements Call {
  

Response getResponseWithInterceptorChain() throws IOException {
  // Build a full stack of interceptors.
  List<Interceptor> interceptors = new ArrayList<>();
//这里可以看出,我们自定义的Interceptor会被优先执行
  interceptors.addAll(client.interceptors());
//添加重试和重定向拦截器
  interceptors.add(retryAndFollowUpInterceptor);
  interceptors.add(new BridgeInterceptor(client.cookieJar()));
  interceptors.add(new CacheInterceptor(client.internalCache()));
  interceptors.add(new ConnectInterceptor(client));
  if (!forWebSocket) {
    interceptors.addAll(client.networkInterceptors());
  }
  interceptors.add(new CallServerInterceptor(forWebSocket));

  Interceptor.Chain chain = new RealInterceptorChain(interceptors, null, null, null, 0,
      originalRequest, this, eventListener, client.connectTimeoutMillis(),
      client.readTimeoutMillis(), client.writeTimeoutMillis());

  return chain.proceed(originalRequest);
}

}

从上述代码可以看出拦截器调用的先后顺序依次是:

  1. client.interceptors()
  2. RetryAndFollowUpInterceptor
  3. BridgeInterceptor
  4. CacheInterceptor
  5. ConnectInterceptor
  6. client.networkInterceptors()
  7. CallServerInterceptor

下面我们开始解释拦截器

一、拦截器---->Interceptor接口

public interface Interceptor {
  Response intercept(Chain chain) throws IOException;

  interface Chain {
    Request request();

    Response proceed(Request request) throws IOException;

    /**
     * Returns the connection the request will be executed on. This is only available in the chains
     * of network interceptors; for application interceptors this is always null.
     */
//返回将在其上执行请求的连接。 这仅适用于网络拦截器链; 对于应用程序拦截器,它始终为null。
    @Nullable Connection connection();

    Call call();

    int connectTimeoutMillis();

    Chain withConnectTimeout(int timeout, TimeUnit unit);

    int readTimeoutMillis();

    Chain withReadTimeout(int timeout, TimeUnit unit);

    int writeTimeoutMillis();

    Chain withWriteTimeout(int timeout, TimeUnit unit);
  }
}

二、Okhttp内置的拦截器

  • RetryAndFollowUpInterceptor:负责失败重试以及重定向。
  • BridgeInterceptor:负责把用户构造的请求转换为发送给服务器的请求,把服务器返回的响应转换为对用户友好的响应。
  • CacheInterceptor:负责读取缓存以及更新缓存。
  • ConnectInterceptor:负责与服务器建立连接。
  • CallServerInterceptor:负责从服务器读取响应的数据。
接下来我们看看RealInterceptorChain是怎么实现一级级处理的,提取RealInterceptorChain 的主要代码如下

public final class RealInterceptorChain implements Interceptor.Chain {
    public Response proceed(Request request, StreamAllocation streamAllocation, HttpCodec httpCodec,
                            RealConnection connection) throws IOException {
        if (index >= interceptors.size()) throw new AssertionError();

        calls++;

        // If we already have a stream, confirm that the incoming request will use it.
//如果我们已经有一个流,请确认传入的请求将使用它。
        if (this.httpCodec != null && !this.connection.supportsUrl(request.url())) {
            throw new IllegalStateException("network interceptor " + interceptors.get(index - 1)
                    + " must retain the same host and port");
        }

        // If we already have a stream, confirm that this is the only call to chain.proceed().
//如果我们已经有了一个流,请确认这是对chain.proceed()的惟一调用。
        if (this.httpCodec != null && calls > 1) {
            throw new IllegalStateException("network interceptor " + interceptors.get(index - 1)
                    + " must call proceed() exactly once");
        }

        // Call the next interceptor in the chain.
//调用链中的下一个拦截器。
        okhttp3.internal.http.RealInterceptorChain next = new okhttp3.internal.http.RealInterceptorChain(interceptors, streamAllocation, httpCodec,
                connection, index + 1, request, call, eventListener, connectTimeout, readTimeout,
                writeTimeout);
        Interceptor interceptor = interceptors.get(index);
        Response response = interceptor.intercept(next);

        // Confirm that the next interceptor made its required call to chain.proceed().
//确认下一个拦截器对chain.proceed()进行了所需的调用。
        if (httpCodec != null && index + 1 < interceptors.size() && next.calls != 1) {
            throw new IllegalStateException("network interceptor " + interceptor
                    + " must call proceed() exactly once");
        }

        // Confirm that the intercepted response isn't null.
//确认拦截的响应不是null。
        if (response == null) {
            throw new NullPointerException("interceptor " + interceptor + " returned null");
        }

        if (response.body() == null) {
            throw new IllegalStateException(
                    "interceptor " + interceptor + " returned a response with no body");
        }

        return response;
    }
}

这个方法比较有意思,在调用proceed()方法之后,会继续构建一个新的RealInterceptorChain对象(代码上标紫色部分),调用下一个interceptor来继续请求,直到所有interceptor都处理完毕,将得到的response返回。

每一个拦截器都遵循这样一个原则:

@Override public Response intercept(Chain chain) throws IOException {

//1 、Request阶段,该拦截器在Request阶段负责做的事情
    Request request = chain.request();

    //2、 调用RealInterceptorChain.proceed(),其实是在递归调用下一个拦截器的intercept()方法
    response = ((RealInterceptorChain) chain).proceed(request, streamAllocation, null, null);

    //3 、Response阶段,完成了该拦截器在Response阶段负责做的事情,然后返回到上一层的拦截器。
    return response;     
    }
  }

从上面的描述可知:

  • Request是按照interpretor的顺序正向处理
  • Response是逆向处理的。

这参考了OSI七层模型的原理。前面我们也提到过。CallServerInterceptor相当于最底层的物理层, 请求从上到下逐层包装下发,响应从下到上再逐层包装返回。

interceptor的执行顺序:

  1. RetryAndFollowUpInterceptor
  2. BridgeInterceptor
  3.  CacheInterceptor
  4.  ConnectInterceptor
  5. CallServerInterceptor。

接下来我们就一个一个的去分析各个拦截器的作用。

详情请查看:OKHTTP系列(四)--拦截器之RetryAndFollowUpInterceptor重定向拦截器

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值