当前位置: 首页 > article >正文

OKHttp拦截器解析

OKHttp涉及到拦截器大概的执行步骤为:

1.通过newCall生成RealCall对象

具体代码如下:

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

2.调用Call的execute方法

当然这也可以是执行异步任务的enqueue方法,我们这里主要分析execute方法,在这个方法中调用getResponseWithInterceptorChain()从而调用拦截器。
具体代码如下:

/**
   * 同步执行网络请求并返回响应
   *
   * @return 返回响应对象
   * @throws IOException 如果在执行请求过程中发生I/O错误
   */
  @Override public Response execute() throws IOException {
    // 同步锁,确保同一时间只有一个线程执行该方法
    synchronized (this) {
      // 检查是否已经执行过,如果已经执行过则抛出异常
      if (executed) throw new IllegalStateException("Already Executed");
      // 标记为已执行
      executed = true;
    }
    // 捕获调用栈信息,用于调试和错误追踪
    captureCallStackTrace();
    try {
      // 将当前请求添加到调度器中,以便管理和执行
      client.dispatcher().executed(this);
      // 通过拦截器链获取响应
      Response result = getResponseWithInterceptorChain();
      // 如果响应为空,则抛出异常
      if (result == null) throw new IOException("Canceled");
      // 返回响应
      return result;
    } finally {
      // 请求完成后,从调度器中移除当前请求
      client.dispatcher().finished(this);
    }
  }

3.调用拦截器,处理相关拦截操作(责任链模式)

  /**
   * 通过拦截器链获取响应
   *
   * @return 返回响应对象
   * @throws IOException 如果在获取响应过程中发生I/O错误
   */
  Response getResponseWithInterceptorChain() throws IOException {
    // 构建一个完整的拦截器栈
    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));
    // 如果不是WebSocket请求,添加网络拦截器
    if (!forWebSocket) {
      interceptors.addAll(client.networkInterceptors());
    }
    // 添加调用服务器拦截器,用于发送请求和接收响应
    interceptors.add(new CallServerInterceptor(forWebSocket));

    // 创建一个拦截器链
    Interceptor.Chain chain = new RealInterceptorChain(
        interceptors, null, null, null, 0, originalRequest);
    // 执行拦截器链并返回响应
    return chain.proceed(originalRequest);
  }

4.拦截器执行,链式调用

核心类为: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;
  }

  // 这个是拦截器中执行的proceed方法
  @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.
    // 传入下一个拦截器的索引和拦截器List,生成RealInterceptorChain对象
    RealInterceptorChain next = new RealInterceptorChain(
        interceptors, streamAllocation, httpCodec, connection, index + 1, request);
    // 根据当前索引获取拦截器
    Interceptor interceptor = interceptors.get(index);
    // 我们的拦截器实现了intercept(chain)方法,通过intercept实现了调用拦截器链的操作
    Response response = interceptor.intercept(next);

    ... 

    return response;
  }
}

具体我们实现拦截器的简单例子如下:

public class CustomHeaderInterceptor implements Interceptor {

    @Override
    public Response intercept(Chain next) throws IOException {
        Request originalRequest = next.request();

        // 添加自定义头部信息
        Request newRequest = originalRequest.newBuilder()
                .header("Custom-Header", "Custom-Value")
                .build();

        // 继续处理请求,我们可以看到,Response response = interceptor.intercept(next)传下来的next在这里执行了proceed方法。从而实现了链式调用
        return next.proceed(newRequest);
    }
}


http://www.kler.cn/a/535147.html

相关文章:

  • 概念AIGC
  • Ubutun本地部署DeepSeek R1
  • Golang 并发机制-6:掌握优雅的错误处理艺术
  • 前端开发中的“原生模块化”——深入解析ES模块(ESM)的使用与优化
  • Beans模块之工厂模块注解模块CustomAutowireConfigurer
  • simpleQtLogger日志库的使用
  • OpenOffice实现word转pdf
  • 深度整理总结MySQL——行记录存储
  • tcpdump 的工作层次
  • 计算机网络笔记再战——理解几个经典的协议4
  • AI 编程工具—Cursor进阶使用 生成AI工作流
  • 售后板子HDMI无输出分析
  • 力扣.270. 最接近的二叉搜索树值(中序遍历思想)
  • 分析用户请求K8S里ingress-nginx提供的ingress流量路径
  • 服务器升级nginx版本
  • ImportError: cannot import name ‘Undefined‘ from ‘pydantic.fields‘
  • 使用 OpenGL ES 在 iOS 上渲染一个四边形:从基础到实现
  • DKG(Distributed Key Generation)协议
  • 设计模式六大原则和单例模式
  • 依赖版本冲突导致微服务项目启动失败解决方法
  • 数据中台是什么?:架构演进、业务整合、方向演进
  • AI测试工程师成长指南:以DeepSeek模型训练为例
  • 【gjson使用方法】
  • 基于springboot+vue的社区居民诊疗健康管理系统设计与实现
  • [Android] 360行车记录仪谷歌版
  • wxWidgets生成HTML文件,带图片转base64数据