參考及轉載地址
參考地址:Okhttp攔截器Interceptor學習和使用
參考地址:Interceptor介紹
參考地址:OkHttp3.0(四)-Interceptor攔截器(3)-RetryAndFollowUpInterceptor
參考地址:深入理解OkHttp3 (1):Interceptors
轉載和學習地址:Okhttp解析—Interceptor詳解
轉載和學習地址:Okhttp之CacheInterceptor簡單分析
瞭解一下Interceptor
okhttp的攔截器就是將整個請求網絡的過程的每一步都封裝在不同的Interceptor裏,簡單點說就是把一個List裏的Interceptor都順序執行一遍,那麼整個網絡請求過程就完成了。
攔截器從時機上區分爲兩種,ApplicationInterceptor(應用攔截器) 和 NetworkInterceptor(網絡攔截器)。
2.1 添加攔截器
client = new OkHttpClient.Builder()
.addInterceptor(new LogInterceptor())
.build();
client = new OkHttpClient.Builder()
.addNetworkInterceptor(new LogInterceptor())
.build();
攔截器添加有兩種方法。
區別是 addInterceptor 是最先執行的攔截器, addNetworkInterceptor是在ConnectInterceptor之後執行的攔截器。
3. 不是內置的攔截器
3.1 日誌攔截器 HttpLoggingInterceptor
攔截器默認不輸出Log所以使用的時候,需要設置Log輸出級別。
private volatile Level level = Level.NONE;
使用時:
if (BuildConfig.isDebug) {
builder.addInterceptor(new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY));
}
同時,HttpLoggingInterceptor 可以設置用APP的Log工具輸出:
HttpLoggingInterceptor httpLoggingInterceptor =
new HttpLoggingInterceptor(new HttpLoggingInterceptor.Logger() {
@Override
public void log(String message) {
try {
LogUtils.i(TAG, "HTTP ====>>" + message);
} catch (Exception e) {
e.printStackTrace();
}
}
});
內部代碼:
代碼:
Request request = chain.request();
Connection connection = chain.connection();
Protocol protocol = connection != null ? connection.protocol() : Protocol.HTTP_1_1;
String requestStartMessage = "--> " + request.method() + ' ' + request.url() + ' ' + protocol;
輸出:
--> POST http://yoshin.com/app-auth/aa/account/login http/1.1
代碼:
logger.log("<-- " + response.code() + ' ' + response.message() + ' '
+ response.request().url() + " (" + tookMs + "ms" + (!logHeaders ? ", "
+ bodySize + " body" : "") + ')');
輸出:
<-- 200 OK http://yoshin.com/app-auth/aa/account/login (114ms)
3.2 自定義攔截器
自定義的攔截器,請求前的和請求後的使用:
請求前:
Interceptor interceptor = new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
LogUtils.i(TAG, "interceptor ," +
"");
//TODO 請求的攔截器,可以請求前做些操作,比如添加HEADER
Request request = chain.request();
return chain.proceed(request);
}
};
請求後:
Interceptor interceptorResponse = new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
Response response = chain.proceed(request);
LogUtils.i(TAG, "interceptorResponse");
if (request.url().toString().contains(FORUM_SERVER_URL)) {
String json = response.body().string();
//TODO 將JSON解析成對應的BEAN,code = 2019時,可以做些什麼操作
ResponseBody myBody = ResponseBody.create(MediaType.parse("text/json"), json);
//重新生成ResponseBody後,返回
return response.newBuilder().body(myBody).build();
}
return response;
}
};
4. 所有內置攔截器的介紹
4.1 攔截器責任鏈
如下是OKHTTP內置的攔截器:
Response getResponseWithInterceptorChain() throws IOException {
// Build a full stack of interceptors.
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));
if (!forWebSocket) {
interceptors.addAll(client.networkInterceptors());
}
interceptors.add(new CallServerInterceptor(forWebSocket));
Interceptor.Chain chain = new RealInterceptorChain(interceptors, null, null, null, 0,
originalRequest, this, eventListener, client.connectTimeoutMillis(),
client.readTimeoutMillis(), client.writeTimeoutMillis());
return chain.proceed(originalRequest);
}
4.2 重試和重定向攔截器 RetryAndFollowUpInterceptor
原理地址:OkHttp3.0(四)-Interceptor攔截器(3)-RetryAndFollowUpInterceptor
Okhttp 內置的第一個攔截器,t 默認支持失敗重連,如果想修改可以調用如下方法:
//設置失敗重連 true 允許失敗重連,false 不允許失敗重連
public Builder retryOnConnectionFailure(boolean retryOnConnectionFailure) {
this.retryOnConnectionFailure = retryOnConnectionFailure;
return this;
}
4.3 橋接攔截器 BridgeInterceptor
轉載:OkHttp源碼閱讀(五) —— 攔截器之BridgeInterceptor
作用:
- 封裝request頭信息
- 處理cookie信息
- 處理服務器壓縮後的response
核心功能就是將用戶請求完全變成一個真正的網絡請求,具體字段的含義如下:
字段 | 含義 |
---|---|
Content-Type | 定義網絡文件的類型和網頁的編碼,如果未指定 ContentType,默認爲[TEXT]/[HTML] |
Content-Length | 表示的是請求體內容的長度。它和 Transfer-Encoding 是互斥的 |
Transfer-Encoding | 值爲 chunked 表示請求體的內容大小是未知的 |
Host | 客戶端指定想訪問的http服務器的域名/IP和端口號 |
Connection | 默認就是 “Keep-Alive”,就是一個 TCP 連接之後不會關閉,保持連接狀態。 |
Accept-Encoding | 優先的內容編碼,默認是 “gzip” 告訴服務器客戶端支持 gzip 編碼的響應 |
Range | 實體的字節範圍 |
Cookie | 當請求設置了 Cookie 那麼就是添加 Cookie 這個請求頭 |
User-Agent | HTTP客戶端程序的信息 |
4.4 緩存攔截器 CacheInterceptor
作用是:緩存網絡返回的Response
流程圖轉載自:Okhttp之CacheInterceptor簡單分析
4.5 連接攔截器 ConnectInterceptor
ConnectInterceptor,連接攔截器其實就是爲後面的CallServerInterceptor請求服務器攔截器做準備
操作是:
通過Transmitter的newExchange方法創建一個Exchange。
Transmitter是應用和網絡之間的一個橋樑,通過transmitter.newExchange構造一個Exchange實例。
ExchangeFinder就是負責連接的創建,把創建好的連接放入連接池,如果連接池中已經有該連接,就直接取出複用。而ExchangeCodec則是對HTTP請求和HTTP響應編碼
Exchange則是用來進行發送和接收HTTP request和respone。
4.6 CallServerInterceptor
攔截器鏈中最後一個攔截器,與服務器的交互如,發出請求和接收響應都是它完成的