1. 程式人生 > >Retrofit2.0和它的攔截器們

Retrofit2.0和它的攔截器們

之前已經講過了Retrofit2.0的初步認識,不是很清楚的同學可以參看我的文章連結:
Retrofit2.0初識:http://blog.csdn.net/burn_yourself/article/details/71799253


一般的,我們在寫網路通訊的時候,log除錯是必須的,那麼本篇文章就來講講 Retrofit2.0 和 它的 攔截器們,主要包括以下幾方面:
1. Header  攔截器
2. Cache 攔截器
3.log 攔截器


那麼,下面就一一講述新增。
首先,還是需要新增網路許可權,由於快取攔截器,涉及到網路狀態,於是還要多新增一個網路狀態許可權,本篇涉及到的許可權有:
    <uses-permission android:name="android.permission.INTERNET" />
    <!-- 獲取運營商資訊,用於支援提供運營商資訊相關的介面 -->
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />


app 的 gradle 中新增包的引用:
    compile 'com.squareup.retrofit2:retrofit:2.2.0'
    compile 'com.squareup.retrofit2:converter-gson:2.2.0'
注意,由於retrofit2.0 本身就是對okhttp3的一個封裝,所以不必再新增對於okhttp3.X  的引用


由於Retrofit2.0中並沒有對於攔截器的處理,於是還是得在 OKhttp 中去處理攔截的問題,然後將 okhttp 物件 add 到 Retrofit 初始化的程式碼中。
大概思路如此,首先貼出 Retrofit2.0 通訊大致流程,還是以 retrofit2.0 中 獲取簡訊驗證碼為例:


1.宣告api:
public interface ApiService<T>{


    //註冊時獲取簡訊驗證碼
    @POST("api/login/pushSms")
    @FormUrlEncoded
    Call<ApiResponse<SmsCode>> postSms(@FieldMap Map<String, String> map);



2.寫Retrofit物件,並配置網路:
package com.test.http.retrofit;


import com.test.http.interceptor.CacheInterceptor;
import com.test.http.interceptor.HeaderInterceptor;
import com.test.util.LogUtil;


import java.io.File;
import java.util.concurrent.TimeUnit;


import okhttp3.Cache;
import okhttp3.OkHttpClient;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;


/**
 * Created by Admin on 2017/5/12.
 */


public class HttpClient{


    public ApiService mApiService;


    private HttpClient() {
        Cache cache = new Cache(new File(BuildConfig.PATH_CACHE), BuildConfig.DEFAULT_CACHE_SIZE);


        OkHttpClient.Builder builder = new OkHttpClient.Builder()
                .addInterceptor(new HeaderInterceptor())//設定Header
                .addNetworkInterceptor(new CacheInterceptor())//設定快取
                .addInterceptor(new CacheInterceptor())
                .cache(cache)
                .connectTimeout(BuildConfig.DEFAULT_CONNECT_TIMEOUT, TimeUnit.SECONDS)//設定連線超時時間
                .readTimeout(BuildConfig.DEFAULT_READ_TIMEOUT, TimeUnit.SECONDS)//設定讀取超時時間
                .writeTimeout(BuildConfig.DEFAULT_WRITE_TIMEOUT, TimeUnit.SECONDS)//設定寫的超時時間
                .retryOnConnectionFailure(true);//錯誤重連
           //除錯模式列印Log日誌
            if (BuildConfig.DEBUG) {
                builder.addInterceptor(new LoggingInterceptor());
            }


        OkHttpClient client=builder.build();
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(BuildConfig.BASE_URL)
                .client(client)
                .addConverterFactory(GsonConverterFactory.create())
//                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .build();
        mApiService = retrofit.create(ApiService.class);
    }


    private static class HttpClientHolder {
        private static final HttpClient INSTANCE = new HttpClient();
    }


    public static HttpClient getInstance() {
        return HttpClientHolder.INSTANCE;
    }


    public ApiService getApiService() {
        return mApiService;
    }


}


activity中呼叫與接收:
 private void send(Map<String,String>map){
        HttpClient.getInstance().getApiService().postSms(map).enqueue(new Callback<ApiResponse<SmsCode>>() {
            @Override
            public void onResponse(Call<ApiResponse<SmsCode>>call, Response<ApiResponse<SmsCode>>response) {
                int code=response.code();
                ApiResponse apiResponse=response.body();
                SmsCode sms= (SmsCode) apiResponse.getData();


                Log.e(TAG, "sms: "+sms.getStatus());
            }


            @Override
            public void onFailure(Call call, Throwable t) {


                Log.e(TAG, "t"+t.getMessage());
            }
        });
    }


大家細心的話會發現 類 HttpClient 中已經新增得有 攔截器了,HeaderInterceptor,CacheInterceptor,LoggingInterceptor.


攔截器都要實現 Interceptor 介面,首先看 HeaderInterceptor 是怎麼實現的
/**
 * Created by Admin on 2017/5/13.
 * header攔截器,對Header統一處理,涉及到header加密的也在此處理
 */
public class HeaderInterceptor implements Interceptor{
    @Override
    public Response intercept(Chain chain) throws IOException {
        Request request = chain.request();
        //處理業務邏輯,可以對header統一處理,涉及到header加密的也在此處理
        //......
        
        request = builder.build();
        return chain.proceed(request);
    }
}


然後介紹的是 CacheInterceptor :
package com.test.http.interceptor;


import com.test.http.retrofit.BuildConfig;
import com.test.util.NetUtil;


import java.io.IOException;


import okhttp3.CacheControl;
import okhttp3.Interceptor;
import okhttp3.Request;
import okhttp3.Response;


/**
 * Created by Administrator on 2016/11/3.
 * 快取攔截器
 */


public class CacheInterceptor implements Interceptor {
    @Override
    public Response intercept(Chain chain) throws IOException {
        Request request = chain.request();
        if (!NetUtil.isNetworkConnected()) {//沒網強制從快取讀取(必須得寫,不然斷網狀態下,退出應用,或者等待一分鐘後,就獲取不到快取)
            request = request.newBuilder()
                    .cacheControl(CacheControl.FORCE_CACHE)
                    .build();
        }
        Response response = chain.proceed(request);
        if (NetUtil.isNetworkConnected()) {//有網情況下,從伺服器獲取
            int maxAge = BuildConfig.DEFAULT_COOKIE_NETWORK_TIME;
            // 有網路時, 快取最大儲存時長為60s
            response.newBuilder()
                    .header("Cache-Control", "public, max-age=" + maxAge)
                    .removeHeader("Pragma")
                    .build();
        } else {//沒網情況下,一律從快取獲取
            // 無網路時,設定超時為30天
            int maxStale = BuildConfig.DEFAULT_COOKIE_NO_NETWORK_TIME;
            response.newBuilder()
                    .header("Cache-Control", "public, only-if-cached, max-stale=" + maxStale)
                    .removeHeader("Pragma")
                    .build();
        }
        return response;
    }
}


最後介紹我們的 LoggingInterceptor,其實個人認為 LoggingInterceptor 還是比較重要的,Retrofit2.0 中log攔截器的實現有兩種方式,一種是自定義,另一種是呼叫 okhpp中自帶的 log攔截器,
那麼,先介紹 LoggingInterceptor 的實現:
/**
 * Created by Admin on 2017/5/13.
 * 自定義log列印攔截器
 */


public class LoggingInterceptor implements Interceptor{


    @Override
    public Response intercept(Chain chain) throws IOException {
        //這個chain裡面包含了request和response,所以你要什麼都可以從這裡拿
        //=========傳送===========
        Request request = chain.request();
        long requestTime = System.currentTimeMillis();//請求發起的時間
        HttpUrl requestUrl=request.url();
        Connection requestConnection=chain.connection();
        Headers requestHeaders=request.headers();
        //打印發送資訊
        LogUtil.e("===LoggingInterceptor===傳送==requestUrl="+requestUrl);
        LogUtil.e("===LoggingInterceptor===傳送==requestConnection="+requestConnection);
        LogUtil.e("===LoggingInterceptor===傳送==requestHeaders="+requestHeaders);


        //=========接收===========
        long responseTime = System.currentTimeMillis();//收到響應的時間
        Response response = chain.proceed(chain.request());
        ResponseBody responseBody = response.peekBody(1024 * 1024);
        HttpUrl responseUrl=response.request().url();
        String content = response.body().string();
        Headers responseHeaders=response.headers();
        long delayTime=responseTime-requestTime;
        //列印接收資訊
        LogUtil.e("=====LoggingInterceptor===接收==responseUrl="+responseUrl);
        LogUtil.e("=====LoggingInterceptor===接收==responseHeaders="+responseHeaders);
        LogUtil.e("=====LoggingInterceptor===接收==delayTime="+delayTime);
        LogUtil.e("=====LoggingInterceptor===接收==content="+content);


        return response;
    }
}
這裡最需要注意的是 方法中 對 request 和 response 的獲取和處理


自定義 Log除錯類在 HttpClient 中的呼叫順序是 ,先對 okhttp。builder 做些其它基本配置,然後
  除錯模式列印Log日誌
        if (BuildConfig.DEBUG) {
           builder.addInterceptor(new LoggingInterceptor());
        }


最後,在retrofit中加入 okhttp物件
        OkHttpClient client=builder.build();
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(BuildConfig.BASE_URL)
                .client(client)
                .addConverterFactory(GsonConverterFactory.create())
//                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .build();
        mApiService = retrofit.create(ApiService.class);


OKHttp 呼叫系統 Log列印的話,需要在 app。gradle 中新增引用:
compile 'com.squareup.okhttp3:logging-interceptor:3.4.1'


然後在程式碼中這樣寫:
        //呼叫系統log攔截器
        if (BuildConfig.DEBUG) {
            HttpLoggingInterceptor logging = new HttpLoggingInterceptor(
                    new HttpLoggingInterceptor.Logger() {
                        @Override
                       public void log(String message) {
                            LogUtil.e("=======message=="+message);
                        }
                    });
            logging.setLevel(HttpLoggingInterceptor.Level.BODY);
            builder.addInterceptor(logging);
        }


message中會打印出 通訊中各種詳細資訊。


最後,貼出 網路配置檔案程式碼:
/**
 * Created by Admin on 2017/5/12.
 * 網路通訊相關配置
 */


public class BuildConfig {


    public static boolean DEBUG=true;


    /**正試**/
    private final static String RELEASE_URL = "";
    /**測試**/
    private static final String DEBUG_URL = "http://192.168.0.10/";


    public final static String BASE_URL = BuildConfig.DEBUG ? DEBUG_URL : RELEASE_URL;


    public static final int DEFAULT_CACHE_SIZE = 150 * 1024 * 1024; // 50 MiB
    /*超時時間-預設10秒*/
    public static final int DEFAULT_CONNECT_TIMEOUT = 20;
    public static final int DEFAULT_READ_TIMEOUT = 20;
    public static final int DEFAULT_WRITE_TIMEOUT = 20;
    /*有網情況下的本地快取時間預設60秒*/
    public static final int DEFAULT_COOKIE_NETWORK_TIME = 0;
    /*無網路的情況下本地快取時間預設30天*/
    public static final int DEFAULT_COOKIE_NO_NETWORK_TIME = 24 * 60 * 60 * 30;


    public static final String PATH_DATA = MyApplication.getInstance().getCacheDir().getAbsolutePath() + File.separator + "data";
    public static final String PATH_CACHE = PATH_DATA + "/NetCache";


}


OK,今天關於 Retrofit2.0 攔截器就講到這裡,睡覺去了。大家有什麼疑問,或者我理解得有誤的地方,歡迎交流


相關推薦

Retrofit2.0攔截

之前已經講過了Retrofit2.0的初步認識,不是很清楚的同學可以參看我的文章連結: Retrofit2.0初識:http://blog.csdn.net/burn_yourself/article/details/71799253 一般的,我們在寫網路通訊的時候,log

Retrofit2.0新增日誌攔截列印URL一級返回資料

//定製OkHttp OkHttpClient.Builder httpClientBuilder = new OkHttpClient .Builder(); if (BuildConfig.DEBUG) {//釋出版本不再列印 // 日誌顯示級別

SpringMVC案例3----spring3.0項目攔截、ajax、文件上傳應用

his water aop pro 文件夾 創建 adapt 後綴 實現 依然是項目結構圖和所需jar包圖: 顯示配置文件hib-config.xml <?xml version="1.0" encoding=&qu

<head>標簽的小夥伴

容器 hello script charset content 不同 基本 介紹 tro head標簽是HTML文檔中最基本的必須元素之一(body:對,還有我): <html> <head> <title>文檔的標題<

SSH開發 | 配合自定義註解 Stratus攔截,實現 方法級粒度 用戶鑒權

struts OS action gin 所有 具體實現 getmethod red nal 1.提要   本文是 小小商城-SSH版的 細節詳解系列 之一,項目 github:https://github.com/xenv/S-mall-ssh 本文代碼大部分在 gith

springboot 2.0+ 自定義攔截 靜態資源問題

per static index 進行 onf 自定義攔截器 tor gis css 之前項目的springboot自定義攔截器使用的是繼承WebMvcConfigurerAdapter重寫常用方法的方式來實現的.靜態文件不需要進行放行,springboot會自動幫你放行。

Retrofit2.0RxJava2.0的簡單封裝

一、首先新增專案依賴: implementation "com.squareup.okhttp3:logging-interceptor:$var.loggingInterceptor"

Retrofit rxjava2的簡單使用封裝utils 日誌攔截

依賴*********注意網路許可權 //rxjava依賴     implementation 'io.reactivex.rxjava2:rxandroid:2.0.2'     implementation 'io.reactivex.rxjava2:rxjava:2

Java過濾器SpringMVC攔截之間的關係與區別

  由於最近做的專案中有一部分是介面遠端呼叫,用到了接入許可權和業務許可權的鑑定,需要採用SpringMVC的攔截器,以前用Struts2的時候用過攔截器,而SpringMVC的攔截器功能之前沒研究過,所以這次來稍微研究一下,得出的結論是SpringMVC的攔截器和Struts2的攔截器原理幾乎是一模一樣的,

web工程過濾器springMVC攔截的一些總結

今天自己寫SSO(單點登入)發現一些問題的總結 1。因為原先有攔截器inteceptor,所以想著就直接用攔截器搞好了,後來發現不行, 原因是:工程預設是/訪問,是在web中配置預設的,並沒有呼叫任何方法(而攔截器是攔截方法的),所以無論我修改spring配置檔案,修

Novate:Retrofit2.0RxJava的又一次完美改進加強(Tamic部落格 -CSDN)

作者/Tamic 前言 用過RxJava和Retrofit的朋友,用久了就會發現Retrofit說難不難,說簡不簡,對於實際專案中,單純的用Retrofit做請求庫,開發起來還是很多不便,必須請求頭和引數處理,API介面數目眾多時的處理,

java專案許可權控制的理解示例(基於shiro傳統攔截filter兩種方式)

1.概念 個人理解,許可權就是做到對不同使用者進行訪問限制,前提是保證在許可權需求設計範圍內不會出現非法也能訪問到不該訪問到的東西.因此按資料表設計將許可權分為:部門,使用者,角色,角色許可權中間表,許可權.(個人覺得一般專案可以考慮部門和角色合為一個),這

QtAndroid詳解(2):startActivity的小夥伴

    上一篇,“QtAndroid詳解(1):QAndroidJniObject”,我們做了好多好多準備工作,目的就是為使用 QtAndroid 名字空間裡的 startActivity() 方法呼叫 Android 系統功能奠定基礎。那這次呢,我們就要來研究如何使用 st

springboot 2.0+ 自定義攔截

之前專案的springboot自定義攔截器使用的是繼承WebMvcConfigurerAdapter重寫常用方法的方式來實現的。以下WebMvcConfigurerAdapter 比較常用的重寫介面    /** 解決跨域問題 **/    public void addCo

Java自定義註解 springMVC攔截 配合使用記錄系統操作日誌的案例

自定義註解的用法, 好多人不知道, 在這裡, 程式碼的註釋中, 我已經詳細的介紹了, 另外就是很多人不知道自定義註解如何使用, 這裡配合springMVC攔截器, 做一個非常實用的案例. 案例: 記錄系統操作的日誌 首先是定義註解: package cn.wxy.ssm

springmvcstruts2攔截的簡單使用以及配置

public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)throws Exception {System.out.println("進入方法之後。");}@

retrofit2.0使用攔截Interceptor統一列印請求與響應的json

先新增依賴: compile ‘com.squareup.retrofit2:retrofit:2.1.0’ compile ‘com.squareup.retrofit2:converter-gson:2.1.0’ compile

微服務 SpringBoot 2.0(八):靜態資源攔截處理

一文搞清楚靜態資源和攔截器 —— Java面試必修 引言 接觸一個web專案,首先要確認的就是入口,所以靜態資源和攔截器在專案中是架構級的,在第五章我們整合了Thymeleaf模組,初次認識了SpringBoot對靜態資源的預設支援。今天我們來繼續學習Sp

OkHttp3.0(結合Retrofit2/Rxjava)利用攔截實現全域性超時自動登入、新增統一引數

應用場景:1.服務端為了統計各個平臺、版本的使用情況,有時在介面中要求傳遞統一的諸如version(客戶端版本)、os(客戶端平臺android/iOS)、userId等引數,這時如果在介面中一一新增就比較繁瑣了,考慮做全域性處理;另外,一次登入成功後,

springMVC攔截過濾器總結

cal .org 文件 bat system als request ping blog 攔截器: 用來對訪問的url進行攔截處理 用處: 權限驗證,亂碼設置等 spring-mvc.xml文件中的配置: <beans xmlns="http://www.sprin