okhttp-緩存機制

okhttp提供緩存機制,用於緩存響應head和body,但默認是不開啓緩存機制。

啓用緩存:

new OkHttpClient().newBuilder().cache(new Cache(new File(“D:/”), 10240)).build();

緩存執行基本流程:

1.執行攔截器鏈CacheInterceptor,首先會從緩存中讀取響應結果
2.okhttp提供Cache類作爲緩存的基本操作類,實際緩存操作是通過該類執行

緩存實現基本原理:

存儲:
1.okhttp緩存存儲是基於文件存儲,從啓用緩存機制傳入的兩個參數也可以看出:directory->緩存文件目錄,maxSize->緩存支持存儲的最大字節數
清理:
1.緩存清理是基於LRU機制,清理最老且使用最少的數據
2.內部維護一個清理線程,當size大於或等於maxSize時就會執行清理操作

關於緩存文件,可以參考一段源碼註釋:

  • This cache uses a journal file named “journal”. A typical journal file
    looks like this:
    libcore.io.DiskLruCache
    1
    100
    2
    CLEAN 3400330d1dfc7f3f7f4b8d4d803dfcf6 832 21054
    DIRTY 335c4c6028171cfddfbaae1a9c313c52
    CLEAN 335c4c6028171cfddfbaae1a9c313c52 3934 2342
    REMOVE 335c4c6028171cfddfbaae1a9c313c52
    DIRTY 1ab96a171faeeee38496d8b330771a7a
    CLEAN 1ab96a171faeeee38496d8b330771a7a 1600 234
    READ 335c4c6028171cfddfbaae1a9c313c52
    READ 3400330d1dfc7f3f7f4b8d4d803dfcf6
    The first five lines of the journal form its header. They are the
    constant string “libcore.io.DiskLruCache”, the disk cache’s version,
    the application’s version, the value count, and a blank line.
    Each of the subsequent lines in the file is a record of the state of a
    cache entry. Each line contains space-separated values: a state, a key,
    and optional state-specific values.
    o DIRTY lines track that an entry is actively being created or updated.
    Every successful DIRTY action should be followed by a CLEAN or REMOVE
    action. DIRTY lines without a matching CLEAN or REMOVE indicate that
    temporary files may need to be deleted.
    o CLEAN lines track a cache entry that has been successfully published
    and may be read. A publish line is followed by the lengths of each of
    its values.
    o READ lines track accesses for LRU.
    o REMOVE lines track entries that have been deleted.
    The journal file is appended to as cache operations occur. The journal may
    occasionally be compacted by dropping redundant lines. A temporary file named
    “journal.tmp” will be used during compaction; that file should be deleted if
    it exists when the cache is opened.

解釋:
1.前五行內容描述的是緩存版本信息相關
2.後面每個子行描述的是緩存數據的狀態信息及key對應的信息
3.DIRTY lines->跟蹤被修改的數據
CLEAN lines->每次的DIRTY操作後面都需要跟一個CLEAN/REMOVE操作,表示執行已完成
READ lines->跟蹤每次讀取操作
REMOVE lines->跟蹤每次刪除操作

通過一個簡單例子來測試下okhttp緩存機制

完整源碼:https://github.com/ingorewho/do-test/tree/master/okhttp-test

配置代碼:

/**
 * @Author: ignore1992
 * @Description: 配置okhttp
 * @Date: Created In 17:45 2019/1/30
 */
public class OkhttpConfig {
    private static volatile OkHttpClient client = null;

    public static OkHttpClient client(){
        if (client == null){
            synchronized (OkhttpConfig.class){
                if (client == null){
                    client = new OkhttpConfig().init();
                }
            }
        }
        return client;
    }

    public OkHttpClient init(){
        OkHttpClient.Builder builder = new OkHttpClient().newBuilder();
        builder.connectTimeout(5, TimeUnit.SECONDS)
                .readTimeout(10, TimeUnit.SECONDS)
                .writeTimeout(10, TimeUnit.SECONDS)
                .addInterceptor(new TestInterceptor())
                .addInterceptor(new OkInterceptor())
                .addNetworkInterceptor(new OkNetInterceptor())
                .retryOnConnectionFailure(true)
                .cache(new Cache(new File("D:/"), 10240))
                .sslSocketFactory(getTrustedSSLSocketFactory())
                .hostnameVerifier(DO_NOT_VERIFY);
        return builder.build();
    }

    TrustManager[] trustAllCerts = new TrustManager[]{
            new X509TrustManager() {
                @Override
                public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                    X509Certificate[] x509Certificates = new X509Certificate[0];
                    return x509Certificates;
                }
                @Override
                public void checkClientTrusted(
                        java.security.cert.X509Certificate[] certs, String authType) {
                }
                @Override
                public void checkServerTrusted(
                        java.security.cert.X509Certificate[] certs, String authType) {
                }
            }
    };

    HostnameVerifier DO_NOT_VERIFY = new HostnameVerifier() {
        @Override
        public boolean verify(String hostname, SSLSession session) {
            return true;
        }
    };

    private SSLSocketFactory getTrustedSSLSocketFactory() {
        try {
            SSLContext sc = SSLContext.getInstance("SSL");
            sc.init(null, trustAllCerts, new java.security.SecureRandom());
            return sc.getSocketFactory();
        } catch (KeyManagementException | NoSuchAlgorithmException e) {
            e.printStackTrace();
            return null;
        }
    }
}

測試代碼:

/**
 * @Author: ignore1992
 * @Description:
 * @Date: Created In 14:48 2019/1/31
 */
public class Main {
    public static void main(String[] args) {
        //1.重複執行get同步請求,爲了方便查看緩存命中信息
        System.out.println(ProcessOkhttp.get("https://api.apiopen.top/searchAuthors?name=%E6%9D%8E%E7%99%BD", null));
        System.out.println(ProcessOkhttp.get("https://api.apiopen.top/searchAuthors?name=%E6%9D%8E%E7%99%BD", null));
    }
}

查看緩存目錄下:D:/文件夾下出現三個文件:
journal文件(記錄緩存操作記錄)
99e43630a8fed826b8b19a06e1b8d09e.0文件(記錄header信息)
99e43630a8fed826b8b19a06e1b8d09e.1文件(記錄body信息)

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