拦截器基础概念:OkHttp 拦截器链、Interceptor 接口、intercept 方法签名
原理概述
OkHttp 的拦截器(Interceptor)是贯穿整个 HTTP 请求生命周期的核心扩展点。每个拦截器负责在请求发送前、响应返回后执行自定义逻辑,多个拦截器以链式结构串联,形成一个有序的拦截器链(Interceptor Chain)。
当 OkHttp 发起一个请求时,请求会依次经过注册的所有拦截器,每个拦截器可读取/修改请求、记录日志、重试、缓存、添加头信息等。处理后通过 chain.proceed() 将请求传递给下一个拦截器,最终到达网络层。响应则沿原路反向流回,每个拦截器在拿到响应后也可进行后处理。
核心接口与签名
| 接口/类 | 说明 | 关键方法签名 |
|---|---|---|
Interceptor |
拦截器接口,所有自定义拦截器需实现该接口 | Response intercept(Chain chain) |
Chain |
拦截器链,提供请求对象并传递到下一拦截器 | Request request()Response proceed(Request request) |
Request |
请求对象,包含 URL、方法、Header、Body | Builder 模式构造,不可变 |
Response |
响应对象,包含状态码、Header、Body | Builder 模式构造,不可变 |
拦截器链执行流程
下图展示了两个自定义拦截器在链中的顺序执行与数据流转:
intercept 方法签名解析
public interface Interceptor {
Response intercept(Chain chain) throws IOException;
}
唯一方法 intercept 接收 Chain 对象,返回 Response 对象。典型实现模式:
class LoggingInterceptor implements Interceptor {
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
// 请求前处理
long t1 = System.nanoTime();
Response response = chain.proceed(request);
// 响应后处理
long t2 = System.nanoTime();
System.out.println("请求耗时: " + (t2 - t1) / 1e6 + " ms");
return response;
}
}
关键设计点:
chain.proceed()只能调用一次(除非实现重试/重定向逻辑),否则会抛出异常。Request对象不可变,需要修改时应通过request.newBuilder()创建新实例。- 拦截器可感知请求/响应完整结构,包括 Header、Body、连接属性。
拦截器类型对比
| 类型 | 注册方式 | 触发时机 | 典型用途 |
|---|---|---|---|
| 应用拦截器 | addInterceptor() | 在重定向/重试之前,只执行一次 | 日志、压缩、统一头处理 |
| 网络拦截器 | addNetworkInterceptor() | 在连接建立后,每次网络请求都会触发 | 调试网络细节、修改连接参数 |
常见错误:忘记在自定义拦截器中调用
chain.proceed(request) 会导致请求挂死;重复调用 proceed 会抛出 IllegalStateException。务必在拦截器内部保持正确的链式调用。