目录
七、addInterceptor与addNetworkInterceptor的区别
一、OkHttp3的拦截器
在OkHttp3中,在执行RealCall的execute方法时,在通过HttpClient的Dispatcher执行execute方法后,将当前RealCall添加到执行/等待队列中,然后调用getResponseWithInterceptorChain()方法返回的Response;
在getResponseWithInterceptorChain()方法中,在真正执行网络请求前,会先添加上一串拦截器Interceptor,如下所示:
/** getResponseWithInterceptorChain@RealCall.class */
/** 执行网络请求,并返回服务器响应Response */
Response getResponseWithInterceptorChain() throws IOException {
// Build a full stack of interceptors.
// 拦截器容器
List<Interceptor> interceptors = new ArrayList<>();
// 1.先添加用户自定义的拦截器
interceptors.addAll(client.interceptors());
// 2.重试与重定向拦截器,如重连接,对3xx系列重连接做出响应
interceptors.add(new RetryAndFollowUpInterceptor(client));
// 3.桥接拦截器,切换对用户友好的Request/Response与对服务器友好的Request/Response;
interceptors.add(new BridgeInterceptor(client.cookieJar()));
// 4.缓存拦截器,用来处理网络缓存;
interceptors.add(new CacheInterceptor(client.internalCache()));
// 5.IO连接拦截器,真实IO操作;
interceptors.add(new ConnectInterceptor(client));
if (!forWebSocket) {
// 6.如果不是WebSocket长链接,添加用户自定义的网络拦截器
interceptors.addAll(client.networkInterceptors());
}
// 7.服务器连接拦截器,连接服务器;
interceptors.add(new CallServerInterceptor(forWebSocket));
// 创建拦截器链的实例
Interceptor.Chain chain = new RealInterceptorChain(interceptors, transmitter, null,0,
originalRequest, this, client.connectTimeoutMillis(),
client.readTimeoutMillis(), client.writeTimeoutMillis());
boolean calledNoMoreExchanges = false;
try {
// 开始递归调用不同拦截器,并得到服务器返回结果
Response response = chain.proceed(originalRequest);
if (transmitter.isCanceled()) {
closeQuietly(response);
throw new IOException("Canceled");
}
return response;
} catch (IOException e) {
calledNoMoreExchanges = true;
throw transmitter.noMoreExchanges(e);
} finally {
if (!calledNoMoreExchanges) {
transmitter.noMoreExchanges(null);
}
}
}
二、Interceptor接口
/** Interceptor.class interface*/
/**
* Observes, modifies, and potentially short-circuits requests going out and the corresponding
* responses coming back in. Typically interceptors add, remove, or transform headers on the
* request or response.
*/
public interface Interceptor {
/** 入参为拦截器链,返回值为Http响应Response */
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.
*/
@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);
}
}
每个Interceptor都要实现Interceptor接口;其中intercept()方法作为拦截器的拦截方法,执行具体逻辑,proceed()方法作为递归调用下一个拦截器的方法,从而保证拦截器链按顺序执行下去;
三、RetryAndFollowUpInterceptor
重连接与重定向拦截器:在intercept()方法中先做好网络连接前的准备,如果网络请求没有被取消掉,就开始递归调用proceed方法,获取下一层Interceptor的返回值,赋值给Response对象,在递归的过程中可能会出现异常,比如服务器返回3XX类型的重定向Reponse,则根据Response携带的信息,在followUpRequest方法中创建新的Request对象,这里命名为followUp。默认最多可重定向20次,超过20次则抛出异常;如果出现IO类连接关闭异常,则会重试;
/** intercept@RetryAndFollowUpInterceptor */
/** 拦截方法 */
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
RealInterceptorChain realChain = (RealInterceptorChain) chain;
Transmitter transmitter = realChain.transmitter();
int followUpCount = 0;
Response priorResponse = null;
while (true) {
transmitter.prepareToConnect(request);
if (transmitter.isCanceled()) {
throw new IOException("Canceled");
}
Response response;
boolean success = false