OkHttp 拦截器工作原理

OkHttp 拦截器工作原理

OkHttp 的拦截器(Interceptor)是其核心特性之一,它允许你在请求发送前或响应返回后对数据进行拦截和处理。这种机制为日志记录、请求参数修改、缓存处理等功能提供了强大的扩展能力。

拦截器的工作流程

OkHttp 的拦截器采用责任链模式(Chain of Responsibility),形成一个有序的拦截器链。当发起一个请求时,请求会依次通过每个拦截器的处理,最终到达服务器;响应返回时,则按相反顺序再次经过拦截器链。

拦截器链分为两个主要部分:

  1. 应用拦截器(Application Interceptors):由用户显式添加的拦截器,位于链条前端。
  2. 网络拦截器(Network Interceptors):由 OkHttp 内部添加的拦截器,负责处理与网络相关的操作,位于链条后端。
拦截器接口与关键方法

拦截器需要实现 Interceptor 接口,主要方法是 intercept(Chain chain)

public interface Interceptor {
    Response intercept(Chain chain) throws IOException;
    
    interface Chain {
        Request request();           // 获取当前请求
        Response proceed(Request request) throws IOException; // 将请求传递给下一个拦截器
        Connection connection();     // 获取网络连接信息(仅网络拦截器可用)
    }
}

intercept 方法中,你可以:

  • 修改请求(如添加 headers、参数)
  • 记录请求日志
  • 提前返回响应(如使用缓存)
  • 处理响应(如解密、解析数据)
  • 捕获异常并进行重试
拦截器链的执行顺序

典型的拦截器链执行顺序如下:

  1. 用户添加的应用拦截器(按添加顺序执行)
  2. RetryAndFollowUpInterceptor:处理失败重试和重定向
  3. BridgeInterceptor:将用户的请求转换为网络请求(如添加默认 headers)
  4. CacheInterceptor:处理缓存逻辑
  5. ConnectInterceptor:建立网络连接
  6. 用户添加的网络拦截器(按添加顺序执行)
  7. CallServerInterceptor:向服务器发送请求并接收响应
应用拦截器 vs 网络拦截器
特性应用拦截器网络拦截器
添加方式client.addInterceptor()client.addNetworkInterceptor()
执行位置拦截器链前端拦截器链后端(网络层)
可见范围原始请求和最终响应经过各种转换后的网络请求
是否看到重定向/重试否(仅看到原始请求)是(能看到所有中间请求)
是否看到缓存响应是(可直接返回缓存)否(缓存响应不会到达此处)
典型应用场景日志记录、添加公共参数、请求加密网络监控、响应压缩、调试网络问题
自定义拦截器示例

下面是一个简单的日志拦截器示例,用于记录请求和响应信息:

public class LoggingInterceptor implements Interceptor {
    @Override
    public Response intercept(Chain chain) throws IOException {
        // 记录请求信息
        Request request = chain.request();
        long t1 = System.nanoTime();
        Logger.d(String.format("Sending request %s on %s%n%s",
                request.url(), chain.connection(), request.headers()));

        // 将请求传递给下一个拦截器并获取响应
        Response response = chain.proceed(request);

        // 记录响应信息
        long t2 = System.nanoTime();
        Logger.d(String.format("Received response for %s in %.1fms%n%s",
                response.request().url(), (t2 - t1) / 1e6d, response.headers()));

        return response;
    }
}

使用方式:

OkHttpClient client = new OkHttpClient.Builder()
    .addInterceptor(new LoggingInterceptor()) // 添加应用拦截器
    .build();
拦截器的高级应用
  1. 添加公共参数

    Request newRequest = request.newBuilder()
        .addHeader("Authorization", "Bearer token")
        .build();
    return chain.proceed(newRequest);
    
  2. 请求重试机制

    for (int i = 0; i < maxRetries; i++) {
        try {
            return chain.proceed(request);
        } catch (IOException e) {
            if (i == maxRetries - 1) throw e;
        }
    }
    
  3. 缓存策略

    Response response = chain.proceed(request);
    return response.newBuilder()
        .header("Cache-Control", "max-age=60") // 缓存1分钟
        .build();
    
总结

拦截器是 OkHttp 最强大的特性之一,通过责任链模式实现了灵活的请求/响应处理机制。合理使用拦截器可以帮助你统一处理日志、认证、缓存、重试等横切关注点,提高代码复用性和可维护性。理解应用拦截器和网络拦截器的区别,并根据需求选择合适的拦截器类型,是使用好 OkHttp 的关键。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值