每天記錄學習的新知識 :OKHTTP的攔截器瞭解下

參考及轉載地址

參考地址: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

作用:

  1. 封裝request頭信息
  2. 處理cookie信息
  3. 處理服務器壓縮後的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

攔截器鏈中最後一個攔截器,與服務器的交互如,發出請求和接收響應都是它完成的

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章