OkHttp 的拦截器有哪些

OkHttp 的拦截器主要分为两大类:内置拦截器自定义拦截器。以下是详细的分类和说明:


一、内置拦截器(OkHttp 自动添加)

这些拦截器由 OkHttp 内部自动管理,按照固定顺序执行:

  1. RetryAndFollowUpInterceptor

    • 处理请求失败后的重试和 HTTP 重定向(如 301/302 状态码)
    • 自动处理认证挑战(如 401 认证失败)
  2. BridgeInterceptor

    • 补全缺失的请求头(如 Content-TypeHostUser-Agent
    • 自动处理 Gzip 压缩(添加 Accept-Encoding 头,解压响应体)
  3. CacheInterceptor

    • 根据缓存策略管理本地缓存
    • 处理条件请求(如 If-Modified-Since 头)
  4. ConnectInterceptor

    • 建立与服务器的 TCP/TLS 连接
    • 管理连接池(复用已有连接)
  5. CallServerInterceptor

    • 最终向服务器发送请求并读取响应
    • 处理请求体和响应体的读写

二、自定义拦截器(开发者手动添加)

通过 OkHttpClient.Builder 添加,分为两种类型:

1. 应用拦截器(Application Interceptors)
  • 添加方式.addInterceptor()
  • 特点
    • 最先执行,最后获得响应
    • 能拦截所有请求(包括缓存响应)
    • 无法访问 Connection 对象(如 TLS 信息)
  • 典型用途
    • 统一添加请求头(如 Token)
    • 全局日志记录
    • 请求/响应数据加解密
val client = OkHttpClient.Builder()
    .addInterceptor(LoggingInterceptor()) // 应用拦截器
    .build()
2. 网络拦截器(Network Interceptors)
  • 添加方式.addNetworkInterceptor()
  • 特点
    • 仅在建立网络连接时触发(不拦截缓存响应)
    • 可以访问 Connection 对象(如服务器 IP、TLS 协议)
    • 会跟随重定向和重试
  • 典型用途
    • 网络层监控(如统计请求耗时)
    • 修改重试策略
    • 调试网络细节
val client = OkHttpClient.Builder()
    .addNetworkInterceptor(StethoInterceptor()) // 网络拦截器
    .build()

三、常用自定义拦截器示例

1. 日志拦截器
class LoggingInterceptor : Interceptor {
    override fun intercept(chain: Interceptor.Chain): Response {
        val request = chain.request()
        // 记录请求信息
        val response = chain.proceed(request)
        // 记录响应信息
        return response
    }
}
2. 认证拦截器
class AuthInterceptor(private val token: String) : Interceptor {
    override fun intercept(chain: Interceptor.Chain): Response {
        val newRequest = chain.request()
            .newBuilder()
            .header("Authorization", "Bearer $token")
            .build()
        return chain.proceed(newRequest)
    }
}
3. 缓存控制拦截器
class CacheControlInterceptor : Interceptor {
    override fun intercept(chain: Interceptor.Chain): Response {
        val request = chain.request()
        val modifiedRequest = request.newBuilder()
            .header("Cache-Control", "public, max-age=60")
            .build()
        return chain.proceed(modifiedRequest)
    }
}
4. 请求重试拦截器
class RetryInterceptor(private val maxRetries: Int) : Interceptor {
    override fun intercept(chain: Interceptor.Chain): Response {
        var lastException: IOException? = null
        for (i in 1..maxRetries) {
            try {
                return chain.proceed(chain.request())
            } catch (e: IOException) {
                lastException = e
                Thread.sleep(i * 1000L) // 指数退避
            }
        }
        throw lastException!!
    }
}

四、拦截器执行顺序图示

应用拦截器(开发者添加)
↓
RetryAndFollowUpInterceptor(内置)
↓
BridgeInterceptor(内置)
↓
CacheInterceptor(内置)
↓
ConnectInterceptor(内置)
↓
网络拦截器(开发者添加)
↓
CallServerInterceptor(内置)

五、如何选择拦截器类型?

场景推荐类型
统一添加请求头应用拦截器
全局日志记录应用拦截器
监控实际网络请求网络拦截器
调试 TLS/连接信息网络拦截器
修改重定向行为重写 RetryAndFollowUpInterceptor

六、注意事项

  1. 性能影响:拦截器中的耗时操作会阻塞网络请求
  2. 修改请求体:需谨慎处理,避免破坏数据一致性
  3. 错误处理:拦截器中的异常会直接中断请求链
  4. 线程安全:拦截器可能被多个线程同时调用

OkHttp 的拦截器机制是其强大灵活性的核心,合理使用可以高效实现统一认证、日志、缓存等全局功能。

OkHttp 提供了两种类型的拦截器:**应用拦截器(Application Interceptor)** 和 **网络拦截器(Network Interceptor)**。这两种拦截器的作用和使用场景有所不同。 以下是关于 OkHttp 拦截器的详细介绍: ### 1. 应用拦截器(Application Interceptor) 应用拦截器适用于所有请求,无论它们是直接发送到网络还是从缓存中获取的响应。它可以在请求被发送之前或响应被接收之后执行自定义逻辑。 #### 示例代码: ```java import okhttp3.*; import java.io.IOException; public class ApplicationInterceptorExample { public static void main(String[] args) throws IOException { OkHttpClient client = new OkHttpClient.Builder() .addInterceptor(new LoggingInterceptor()) // 添加应用拦截器 .build(); Request request = new Request.Builder() .url("https://example.com") .build(); try (Response response = client.newCall(request).execute()) { System.out.println(response.body().string()); } } // 自定义应用拦截器 static class LoggingInterceptor implements Interceptor { @Override public Response intercept(Chain chain) throws IOException { Request request = chain.request(); long t1 = System.nanoTime(); System.out.println("Sending request: " + request.url()); Response response = chain.proceed(request); long t2 = System.nanoTime(); System.out.println("Received response for " + response.request().url() + " in " + (t2 - t1) / 1e6 + "ms"); return response; } } } ``` ### 解释: - **`addInterceptor()`**:用于添加应用拦截器。 - **`chain.request()`**:获取当前请求对象。 - **`chain.proceed(request)`**:继续处理请求并返回响应。 --- ### 2. 网络拦截器(Network Interceptor) 网络拦截器仅适用于通过网络发送的请求和接收到的响应。如果请求是从缓存中获取的,则不会调用网络拦截器。 #### 示例代码: ```java import okhttp3.*; import java.io.IOException; public class NetworkInterceptorExample { public static void main(String[] args) throws IOException { OkHttpClient client = new OkHttpClient.Builder() .addNetworkInterceptor(new LoggingNetworkInterceptor()) // 添加网络拦截器 .build(); Request request = new Request.Builder() .url("https://example.com") .build(); try (Response response = client.newCall(request).execute()) { System.out.println(response.body().string()); } } // 自定义网络拦截器 static class LoggingNetworkInterceptor implements Interceptor { @Override public Response intercept(Chain chain) throws IOException { Request request = chain.request(); long t1 = System.nanoTime(); System.out.println("Sending request over network: " + request.url()); Response response = chain.proceed(request); long t2 = System.nanoTime(); System.out.println("Received network response for " + response.request().url() + " in " + (t2 - t1) / 1e6 + "ms"); return response; } } } ``` ### 解释: - **`addNetworkInterceptor()`**:用于添加网络拦截器。 - **网络拦截器的特点**:只有在网络请求发生时才会被调用,因此适合用于记录网络流量或修改网络请求/响应。 --- ### 应用拦截器与网络拦截器的区别: | 特性 | 应用拦截器 | 网络拦截器 | |--------------------------|-------------------------------------|-------------------------------------| | 调用时机 | 所有请求都会触发 | 仅在网络请求时触发 | | 缓存支持 | 支持缓存请求 | 不支持缓存请求 | | 使用场景 | 日志记录、请求头修改等 | 网络流量日志、重试机制等 | --- ### 注意事项: 1. **拦截器顺序**:拦截器的执行顺序与其添加的顺序一致。 2. **链式调用**:确保在拦截器中调用 `chain.proceed(request)`,否则请求将无法继续。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值