OKHttp3初始化與配置

OKHttp3初始化與配置

OKhttp在使用時,最基本的組成部分是OkHttpClient、Request、Call和Response,需要進行初始化的主要是OkHttpClient和Request。

OKHttpClient

一般情況下,全局只需一個OkHttpClient實例(強烈建議),便可以滿足整個應用的Http請求,其主要是由OkHttpClient.Builder的建造者模式來進行配置和初始化的,如可創建一個用於普通http請求的公用OkHttpClient實例:

OkHttpClient okHttpClient = new OkHttpClient.Builder().build();

也可以創建定製化的實例:

OkHttpClient customClient = okHttpClient.newBuilder()
.readTimeout(10000, TimeUnit.MILLISECONDS)
.build();

定製化的OkHttpClient與原實例共享連接池、線程池和公共配置項。OkHttpClient的配置項位於build方法前。

常用配置項

OkHttpClient client = new OkHttpClient.Builder()
        .connectTimeout(60, TimeUnit.SECONDS)      //設置連接超時
        .readTimeout(60, TimeUnit.SECONDS)         //設置讀超時
        .writeTimeout(60, TimeUnit.SECONDS)        //設置寫超時
        .retryOnConnectionFailure(true)            //是否自動重連
        .build();  

Https配置

對於https(此處可簡單複習一下https簡單原理),需要配置sslSocketFactory,一般如需忽略所有證書的話,可以這樣配置:

client = new OkHttpClient.Builder()
        // 設置https配置,此處忽略了所有證書
        .sslSocketFactory(createEasySSLContext().getSocketFactory(), new EasyX509TrustManager(null))  
        .build();  
private static SSLContext createEasySSLContext() throws IOException {
    try {
        SSLContext context = SSLContext.getInstance("TLS");
        context.init(null, null, null);
        return context;
    } catch (Exception e) {
        throw new IOException(e.getMessage());
    }
}
public class EasyX509TrustManager implements X509TrustManager {

    private X509TrustManager standardTrustManager = null;

    /**
     * Constructor for EasyX509TrustManager.
     */
    public EasyX509TrustManager(KeyStore keystore) throws NoSuchAlgorithmException,
            KeyStoreException {
        super();
        TrustManagerFactory factory = TrustManagerFactory.getInstance(TrustManagerFactory
                .getDefaultAlgorithm());
        factory.init(keystore);
        TrustManager[] trustmanagers = factory.getTrustManagers();
        if (trustmanagers.length == 0) {
            throw new NoSuchAlgorithmException("no trust manager found");
        }
        this.standardTrustManager = (X509TrustManager)trustmanagers[0];
    }

    /**
     * @see X509TrustManager#checkClientTrusted(X509Certificate[],
     *      String authType)
     */
    public void checkClientTrusted(X509Certificate[] certificates, String authType)
            throws CertificateException {
        standardTrustManager.checkClientTrusted(certificates, authType);
    }

    /**
     * @see X509TrustManager#checkServerTrusted(X509Certificate[],
     *      String authType)
     */
    public void checkServerTrusted(X509Certificate[] certificates, String authType)
            throws CertificateException {
        if ((certificates != null) && (certificates.length == 1)) {
            certificates[0].checkValidity();
        } else {
            standardTrustManager.checkServerTrusted(certificates, authType);
        }
    }

    /**
     * @see X509TrustManager#getAcceptedIssuers()
     */
    public X509Certificate[] getAcceptedIssuers() {
        return this.standardTrustManager.getAcceptedIssuers();
    }
}

此外還可以使用以下代碼忽略本地校驗url正確性:

.hostnameVerifier(new HostnameVerifier() {
    @Override
    public boolean verify(String hostname, SSLSession session) {
        return true;
    }
})  // 驗證服務器的證書域名。在https握手期間,如果 URL 的主機名和服務器的標識主機名不匹配,則驗證機制可以回調此接口的實現程序來確定是否應該允許此連接

攔截器

攔截器有兩種,應用攔截器和網絡攔截器:
Okhttp3攔截器
詳細的攔截器分析說明可見此處,我們最常使用的攔截器就是網絡日誌打印功能了:

.addInterceptor(new Interceptor() {
    @Override
    public Response intercept(Chain chain) throws IOException {
        Request request = chain.request();
        Log.d("intercept",  "接口地址:" + request.url()
                    + "\r\n接口參數(這裏一般不直接toString,body裏的是stream):" + request.body().toString());
        }
        return chain.proceed(chain.request());
    }
}) // 日誌記錄

其他與https相關的配置項(以下可忽略,一般不用設置,純當筆記,摘自此處):

.certificatePinner(new CertificatePinner.Builder()
        .add("test1.com", "sha1/sdfsdsdsdsdsdsdsdsdsdsdds=")
        .add("test2.com", "sha1/sdsdsdsdsdsdsdsdsdssdssds=")
        .build()) // 添加證書,一般不要設置

添加受信證書,最好不要去設置,詳見此處

.connectionSpecs(...) // 設置連接的規格、TLS版本和密碼套件等

其他設置

.socketFactory(new SocketFactory() {...}) // 使用定製的用於http請求的套接字
.authenticator(new Authenticator() {
    @Override
    public Request authenticate(Route route, Response response) throws IOException {
        ...
    }
}) // 添加授權證書

通過Authenticator類,可以響應來自遠程或者代理服務器的授權驗證,通常情況會返回一個授權頭以做驗證;亦或是返回空表示拒絕驗證。簡單來說,你要訪問一個服務,但是你要對方的驗證。通過Authenticator類來代理一個認證請求,並使用Credentials.basic()來構造一個證書。

.cache(new Cache(new File("cache.tmp"), 10 * 1024 * 1024)) // 10M緩存
.connectionPool(new ConnectionPool(5, 6, TimeUnit.MINUTES))
// 定義連接池,最多有五個空閒連接,每個空閒連接最多保持6分鐘

OkHttp使用共享連接池,默認爲5個5分鐘空閒的連接池。

.cookieJar(new CookieJar() {
    @Override
    public void saveFromResponse(HttpUrl url, List<Cookie> cookies) {
        // response時保存cookie
    }

    @Override
    public List<Cookie> loadForRequest(HttpUrl url) {
        // request發送前,將cookie加到request中
        return ...;
    }
}) // cookie保存和使用

若需要持久化cookie,此篇文章可以借鑑。

.dispatcher(new Dispatcher(new ThreadPoolExecutor(...)))
// 指定分發器,即異步執行http請求時的線程池,http響應的回調也是在此線程池的線程中執行
.dispatcher(new Dispatcher(new ThreadPoolExecutor(...)))
// 指定分發器,即異步執行http請求時的線程池,http響應的回調也是在此線程池的線程中執行
.followRedirects(true)       // 允許http重定向
.followSslRedirects(false)   // 截斷https的重定向

這兩個都是設置是否進行鏈接重定向的。設置爲false時,可以截斷重定向。在一些無限循環重定向的鏈接情況下,通過截斷重定向,並在Call的onResponse中自行處理重定向,可以解決此問題。

.pingInterval(30, TimeUnit.SECONDS) // 設置ping檢測網絡連通性的間隔。默認爲0
.protocols()  // 設置使用的協議,目前支持http1.1和http2,不能包含空和http1.0。一般不會設置
.proxy(...) // 設置單個代理
.proxyAuthenticator(...)  // 設置代理驗證
.proxySelector(...) // 爲不同的鏈接設置不同的代理

Request

Request也如okhttpclient一樣使用構造者模式生成、複用屬性,其主要由四部分組成:
這裏寫圖片描述
Method就是http支持的head、post、get、delete、put、patch:

Request request = new Request.Builder()
        .head()
        .post(requestBody)
        .get()
        .delete().delete(requestBody)
        .put(requestBody)
        .patch(requestBody)
        .method(“post”, requestBody)

Body主要用於post、delete、put、patch時的內容,如提交json字符串:

MediaType JSON = MediaType.parse("application/json; charset=utf-8");
RequestBody rb = RequestBody.create(JSON, jsonString);

Url即指定鏈接:

.url("http://www.baidu.com")
.url(HttpUrl.parse("http://www.baidu.com"))
.url(new HttpUrl.Builder(). ... .build());

Header可以設置請求的頭:

.addHeader("sd", "dsds") // 添加頭部,不會覆蓋舊值
.header("fd", "sdasd")   // 替換相同name的值
.removeHeader("fd")      // 刪除頭部

其他常用設置有:
緩存,針對單個請求:

final CacheControl.Builder builder = new CacheControl.Builder();
builder.noCache();       // 不使用緩存,全部走網絡
builder.noStore();       // 不使用緩存,也不存儲緩存
builder.onlyIfCached();  // 只使用緩存
builder.noTransform();   // 禁止轉碼
builder.maxAge(10, TimeUnit.SECONDS);   // 能接收10秒內的緩存
builder.maxStale(10, TimeUnit.SECONDS); 
// 指示客戶機可以接收超出超時期間的響應消息,即過期後的10秒內緩存可以繼續使用,cache的響應頭部會有提示

builder.minFresh(10, TimeUnit.SECONDS);
// 至少在10秒內,緩存要保持更新
CacheControl cache = builder.build();

xxxRequestBuilder.cacheControl(cache)
.tag("asdsad") // 設置tag,可以用於標記每個request等

參考資料

OKHttp3.0的日常及入門
OkHttp3之Cookies管理及持久化
Class CertificatePinner
square/okhttp的https配置
OkHttp之攔截器
HTTPS工作原理和TCP握手機制

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