1. 程式人生 > >根據Interceptor 分析 OkHttp(二)

根據Interceptor 分析 OkHttp(二)

Interceptor可以說是OkHttp的核心功能,它就是通過Interceptor來完成監控管理、重寫和重試請求的。下面是一個簡單的Interceptor,可以監控request的輸入引數和response的輸出內容。

class LoggingInterceptor implements Interceptor {
  @Override public Response intercept(Interceptor.Chain chain) throws IOException {
    Request request = chain.request();

    long t1 = System.nanoTime();
    logger.info(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.info(String.format("Received response for %s in %.1fms%n%s", response.request().url(), (t2 - t1) / 1e6d, response.headers())); return
response; } }

裡面有個方法呼叫chain.proceed(request),每個Interceptor實現裡都有這個呼叫方法,這個看起來簡單的方法卻是所有的HTTP請求、生成response的關鍵所在。

Interceptors可以被串聯起來(chained)。OkHttp使用lists來管理Interceptors,讓這些Interceptors按順序被呼叫。

Interceptors Diagram

Application Interceptors

我們只能通過Application Interceptors或者Network Interceptors來註冊自定義的Interceptors,其他Interceptors都是OkHttp幫你做好了的,比如RetryAndFollowUpInterceptor、BridgeInterceptor、CacheInterceptor、ConnectInterceptor、CallServerInterceptor。這裡的OkHttp會啟動一個攔截器呼叫鏈,攔截器遞迴呼叫之後最後返回請求的響應Response。這裡的攔截器分層的思想就是借鑑的網路裡的分層模型的思想。請求從最上面一層到最下一層,響應從最下一層到最上一層,每一層只負責自己的任務,對請求或響應做自己負責的那塊的修改。

Interceptors Diagram

Application Interceptors和Network Interceptors分別位於七層模型的第一層和第六層。這個從RealCall裡的getResponseWithInterceptorChain方法中就可以看出來:

Response getResponseWithInterceptorChain() throws IOException {
    // Build a full stack of interceptors.
    List<Interceptor> interceptors = new ArrayList<>();
    interceptors.addAll(client.interceptors()); // Application 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()); // Network Interceptors
    }
    interceptors.add(new CallServerInterceptor(forWebSocket));

    Interceptor.Chain chain = new RealInterceptorChain(
        interceptors, null, null, null, 0, originalRequest);
    return chain.proceed(originalRequest);
  }

我們通過這個LoggingInterceptor 來說明Application Interceptors和Network Interceptors的區別。

通過OkHttpClient.BuilderaddInterceptor()註冊一個 application interceptor:

OkHttpClient client = new OkHttpClient.Builder()
    .addInterceptor(new LoggingInterceptor())
    .build();

Request request = new Request.Builder()
    .url("http://www.publicobject.com/helloworld.txt")
    .header("User-Agent", "OkHttp Example")
    .build();

Response response = client.newCall(request).execute();
response.body().close();

URL http://www.publicobject.com/helloworld.txt會重定向到https://publicobject.com/helloworld.txt,OkHttp會自動follow這次重定向。application interceptor會被呼叫once,並且會返回攜帶有重定向後的redirected response。

INFO: Sending request http://www.publicobject.com/helloworld.txt on null
User-Agent: OkHttp Example

INFO: Received response for https://publicobject.com/helloworld.txt in 1179.7ms
Server: nginx/1.4.6 (Ubuntu)
Content-Type: text/plain
Content-Length: 1759
Connection: keep-alive

我們可以看到,會重定向是因我request的URL和response的URL是不同的,日誌也列印了兩個不同的URLs。

Network Interceptors

註冊一個Network Interceptors的方式是非常類似的,只需要將addInterceptor()替換為addNetworkInterceptor()

OkHttpClient client = new OkHttpClient.Builder()
    .addNetworkInterceptor(new LoggingInterceptor())
    .build();

Request request = new Request.Builder()
    .url("http://www.publicobject.com/helloworld.txt")
    .header("User-Agent", "OkHttp Example")
    .build();

Response response = client.newCall(request).execute();
response.body().close();

當我們執行上面這段程式碼,這個interceptor會執行twice。一次是呼叫在初始的request http://www.publicobject.com/helloworld.txt,另外一次是呼叫在重定向後的redirect request https://publicobject.com/helloworld.txt

INFO: Sending request http://www.publicobject.com/helloworld.txt on Connection{www.publicobject.com:80, proxy=DIRECT hostAddress=54.187.32.157 cipherSuite=none protocol=http/1.1}
User-Agent: OkHttp Example
Host: www.publicobject.com
Connection: Keep-Alive
Accept-Encoding: gzip

INFO: Received response for http://www.publicobject.com/helloworld.txt in 115.6ms
Server: nginx/1.4.6 (Ubuntu)
Content-Type: text/html
Content-Length: 193
Connection: keep-alive
Location: https://publicobject.com/helloworld.txt

INFO: Sending request https://publicobject.com/helloworld.txt on Connection{publicobject.com:443, proxy=DIRECT hostAddress=54.187.32.157 cipherSuite=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA protocol=http/1.1}
User-Agent: OkHttp Example
Host: publicobject.com
Connection: Keep-Alive
Accept-Encoding: gzip

INFO: Received response for https://publicobject.com/helloworld.txt in 80.9ms
Server: nginx/1.4.6 (Ubuntu)
Content-Type: text/plain
Content-Length: 1759
Connection: keep-alive

Application and Network interceptors 該如何選擇

這兩個interceptor都有他們各自的優缺點:

Application Interceptors

  • 不需要關心由重定向、重試請求等造成的中間response產物。
  • 總會被呼叫一次,即使HTTP response是從快取(cache)中獲取到的。
  • 關注原始的request,而不關心注入的headers,比如If-None-Match
  • interceptor可以被取消呼叫,不呼叫Chain.proceed()
  • interceptor可以重試和多次呼叫Chain.proceed()

Network Interceptors

  • 可以操作由重定向、重試請求等造成的中間response產物。
  • 如果是從快取中獲取cached responses ,導致中斷了network,是不會呼叫這個interceptor的。
  • 資料在整個network過程中都可以通過Network Interceptors監聽。
  • 可以獲取攜帶了request的Connection

使用Interceptor的說明

在OkHttp 2.2版本才加入了Interceptor功能,而且,Interceptor不能使用OkUrlFactory,或者是基於OkHttp的低版本第三方庫,比如Retrofit ≤ 1.8 and Picasso ≤ 2.4 。

相關推薦

根據Interceptor 分析 OkHttp

Interceptor可以說是OkHttp的核心功能,它就是通過Interceptor來完成監控管理、重寫和重試請求的。下面是一個簡單的Interceptor,可以監控request的輸入引數和response的輸出內容。 class LoggingI

根據Interceptor 分析 OkHttp

在介紹Interceptor前需要理解幾個概念 Requests 每個HTTP請求都包含一個URL,一個method(比如GET/POST),還有一系列的headers。Requests 還可能包含一個body:一個指定conten

來學學數據分析第一章 預測和關聯數量特征

想要 夠快 均方誤差 容易 預測 適用於 color 就是 工程 Chapter 1 Regression: Predicting and Relating Quantitative Features 1.1 統計學,數據分析,回歸 統計學是利用數學來研究和提高從不完

需求分析說明書

2.任務概述   2.1目標 我們是一款獨立的網站,通過這個網站平臺,任何在讀或畢業學生均可通過網站登入檢視個人資訊,老師及學校管理人員均可登入該平臺實現管理學生資訊。     a.軟體開發的意圖:減少老師的工作量,提高畢業設計資訊的管理效率,使畢業

《深入理解Spark-核心思想與源碼分析第二章Spark設計理念和基本架構

基礎知識 cut info 負責 驅動 源碼分析 spa spark 節點 若夫乘天地之正,而禦六氣之辯解,以遊無窮者,彼且惡乎待哉?

我們為什麼要學習大資料分析

在前面我們給大家說了為什麼要學習大資料分析的原因,比如大資料分析能夠增加從業人員的工資、可以獲得更多的就業機會、大資料分析滲透的領域越來越廣泛等。當然我們學習大資料分析的原因不只是這些,還有很多其他的原因。不過估計大家一時半會想不到更多的學習大資料分析的理由或原因吧?下面就由小編接著給大家講一下這個問題,

產品經理怎麼用好資料分析

在上一篇文章中我們為大家介紹了產品經理為什麼要使用資料分析來工作以及資料分析工作需要的技能,那麼大家知道不知道產品經理需要分析哪些資料呢,資料分析的工具是什麼呢,如何進行資料分析呢?下面就由小編為大家解答一下這些問題。 首先給大家說一下產品經理需要分析哪些資料?產品經理需要分析的資料有很多,就是基礎資料

Python資料分析基礎——NumPy基礎

NumPy最重要的特點就是其N維陣列物件(即ndarray),該物件是一個快速而靈活的大資料集容器。 陣列建立函式 函式 說明 array 將輸入資料(列表、元組、陣列或其他序列型別)轉換為ndarray。 asarray 將輸入轉換為ndarray ara

什麼資料可以使用Excel分析

我們在上一篇文章中給大家介紹了很多的工具使用,其實這些工具的使用遠遠不夠的,要做好資料分析工作還是要學會很多的知識的,下面我們就給大家介紹一下Excel的剩餘工具的使用,希望這篇文章能夠給大家帶來幫助,下面就由小編為大家講解一下這些事情。 首先就是Search和Find類似,區別是Search大小寫不敏

資料分析中的5w2h分析

在上一篇文章中我們為大家簡單地解答了5w2h的具體內容,簡單來說,5w2h就是由7個單片語成的,分別是What(使用者要什麼?)Why(為什麼要?)Where(從哪兒得到?)When(我們什麼時候做?)Who(對誰做?)How much(給多少?)How(怎麼做?)。這7個單詞能夠給大家愛帶來很多的思路,

資料分析中的分組分析

我們在上面的內容中為大家解釋了資料分析中的分組分析方法,我們根據屬性指標分組分析法和數量指標分組分析法的定義給大家進行了詳細的說明。但是對於數量指標分組分析法沒有給大家詳細地說明,今天我們給大家好好講解一下這方面的內容,希望這篇文章能夠幫助到大家。 數量指標分組分析法有單項式分組和組距式分組。現在我們給

京東金融資料分析案例

任務 5 利用 spark streaming 實時分析每個頁面點選次數和不同年齡段消費總金額 步驟:編寫 Kafka produer 程式讀取hdfs上的檔案每隔一段時間產生資料,然後使用spark streaming讀取kafka中的資料進行分析

比特幣原始碼分析-網路

比特幣原始碼分析-網路(二) https://www.jianshu.com/p/4b42d8698f35   眾所周知,比特幣網路是採用的P2P網路體系,所以,沒有明顯的客戶端與服務端的區別或者是概念,每一個節點既是自身的客戶端,又是其它節點的服務端。 在sync.h中,

如何做好資料分析報告

我們在前面的文章中給大家介紹了資料分析報告概況、資料分析報告的型別、資料分析報告的特點與結構。但是隻是知道這些知識是不夠的,我們在進行撰寫資料分析報告的時候還需要做好一些其他工作的。今天我們給大家詳細講解一下資料分析的分析思路和框架。下面就由小編為大家解答一下這個問題,希望能夠給大家帶

0x05演算法設計與分析複習:演算法設計策略-分治法2

參考書籍:演算法設計與分析——C++語言描述(第二版) 演算法設計策略-分治法 二分搜尋 問題描述 在有序表(已按關鍵字值非減排序)中搜索給定元素的問題。 分治法求解 設有一個長度為n的有序表(a0,a1,⋯,an−1),要求

自頂向下深入分析Netty--執行緒模型

上面這幅圖描述了netty的執行緒模型,其中mainReacotor,subReactor,Thread Pool是三個執行緒池。mainReactor負責處理客戶端的連線請求,並將accept的連線註冊到subReactor的其中一個執行緒上;subReactor負責處理客戶端通道上的資料讀

從ECMAScript規範深度分析JavaScript:變數物件

本文譯自Dmitry Soshnikov的《ECMA-262-3 in detail》系列教程。其中會加入一些個人見解以及配圖舉例等等,來幫助讀者更好的理解JavaScript。 宣告:本文不涉及與ES6相關的知識。 前言 在本系列教程上一篇文章《從ECMAScript規範深度分

從ECMAScript規範深度分析JavaScript:變數物件

本文譯自Dmitry Soshnikov的《ECMA-262-3 in detail》系列教程。其中會加入一些個人見解以及配圖舉例等等,來幫助讀者更好的理解JavaScript。 宣告:本文不涉及與ES6相關的知識。 前言 在學習變數物件之前,我們要對執行期上下文有所瞭解,可以先

alsa音效卡驅動分析總結

alsa音效卡驅動分析總結  來自:http://blog.chinaunix.net/uid-20672559-id-3515392.html 現在我們開始分析ASOC: ASoC被分為Machine、Platform和Codec三大部分。其中的Machine驅動負責

eMule 協議分析翻譯

2,客戶機伺服器之間的TCP通訊 每一個客戶端都採用TCP 連線與一個特定的伺服器相連線,伺服器分配給客戶端一個固定的ID。客戶端不能同時連線到幾個伺服器,也不能動態的選擇伺服器,除非由其他客戶端的邀請。 2.1 建立連線 在建立連線的時候,客戶端會向一定數目的伺服器發起