Java 如何在Android上使用HttpsURLConnection和HttpResponseCache强制缓存?

Java 如何在Android上使用HttpsURLConnection和HttpResponseCache强制缓存?,java,android,httpsurlconnection,httpresponsecache,Java,Android,Httpsurlconnection,Httpresponsecache,我有下面的方法从wiktionary.org请求页面,问题是服务器返回Cache control=>private,必须在标题中重新验证,max age=0,这会阻止HttpsURLConnection存储请求 有没有办法强制缓存这些页面 protected static synchronized String getUrlContent(String url) throws ApiException { if (sUserAgent == null) { throw n

我有下面的方法从wiktionary.org请求页面,问题是服务器返回
Cache control=>private,必须在标题中重新验证,max age=0
,这会阻止
HttpsURLConnection
存储请求

有没有办法强制缓存这些页面

protected static synchronized String getUrlContent(String url) throws ApiException {
    if (sUserAgent == null) {
        throw new ApiException("User-Agent string must be prepared");
    }

    try {
        URL obj = new URL(url);
        HttpsURLConnection connection = (HttpsURLConnection) obj.openConnection();

        connection.setRequestMethod("GET");
        connection.setRequestProperty("User-Agent", sUserAgent);
        //connection.addRequestProperty("Cache-Control", "max-stale");
        //connection.addRequestProperty("Cache-Control", "public, max-age=3600");
        //connection.addRequestProperty("Cache-Control", "only-if-cached");

        int responseCode = connection.getResponseCode();
        if (responseCode != HttpURLConnection.HTTP_OK) { // success
            throw new ApiException("Invalid response from server: " + responseCode);
        }

        InputStream inputStream = connection.getInputStream();
        ByteArrayOutputStream content = new ByteArrayOutputStream();

        // Read response into a buffered stream
        int readBytes = 0;
        while ((readBytes = inputStream.read(sBuffer)) != -1) {
            content.write(sBuffer, 0, readBytes);
        }

        HttpResponseCache cache = HttpResponseCache.getInstalled();
        if (cache != null) {
            Log.w("!!!", "Cache hit count: " + cache.getHitCount());
            //connection.addRequestProperty("Cache-Control", "public, max-age=3600");
            Log.w("!!!", "Cache-Control: " + connection.getHeaderField("Cache-Control"));
            //cache.put(new URI(url), connection);
        }

        // Return result from buffered stream
        return new String(content.toByteArray());

    } catch (Exception e) {
        throw new ApiException("Problem communicating with API", e);
    }
}
更新:

仍然无法使用获取缓存命中


在初始化OKHttpClient时,请使用
addNetworkInterceptor
而不是
addInterceptor
重写缓存控制。

为什么不在HTTP请求层上方(例如,在存储库中)自己缓存它们呢?@commonware如果我将域更改为其他支持缓存的站点,那么我需要检查缓存命中,以便自己不缓存数据。似乎无论是
HttpsURLConnection
还是
HttpResponseCache
都没有办法检查这一点。另外,我想也许我可以更改连接对象中的头并将其存储在缓存中,比如so
cache.put(uri,connection)
但这似乎是不可能的。“如果我将域更改为支持缓存的其他站点,那么我需要检查缓存命中,以便自己不缓存数据”——或者,告诉HTTP堆栈不要缓存,并在应用程序层处理它。我不知道
HttpsURLConnection
是否提供了这个功能,尽管OkHttp提供了。可能有一个OkHttp配置可以处理您的目标,尽管我在快速扫描中没有看到。@Commonware用OkHttp更新了我的问题,但仍然无法获得缓存命中率。我可以将
用户代理
放在同一个拦截器中,还是需要第二个拦截器,并用
addInterceptor
添加它?为什么
用户代理需要拦截器?我明白了,你的意思是
request.Builder().addHeader()
…那就可以了,谢谢。
static private OkHttpClient client;
static private Cache cache;

public static OkHttpClient getClient() {
    if (client == null) {
        File cacheDirectory = new File(App.getInstance().getCacheDir().getAbsolutePath(), "HttpCache");
        cache = new Cache(cacheDirectory, 1024 * 1024);
        client = new OkHttpClient.Builder()
                .cache(cache)
                .addInterceptor(REWRITE_CACHE_CONTROL_INTERCEPTOR).build();
    }
    return client;
}

/** Dangerous interceptor that rewrites the server's cache-control header. */
private static final Interceptor REWRITE_CACHE_CONTROL_INTERCEPTOR = new Interceptor() {
    @Override public Response intercept(Interceptor.Chain chain) throws IOException {
        Response originalResponse = chain.proceed(chain.request());
        return originalResponse.newBuilder()
                .header("Cache-Control", "max-age=60")
                .build();
    }
};

protected static synchronized String getUrlContent(String url) throws ApiException {
    try {

        OkHttpClient httpClient = getClient();

        Request request = new Request.Builder()
                .url(url)
                .build();

        Response response = httpClient.newCall(request).execute();

        Log.w("!!!", "hitCount: " + cache.hitCount());

        return response.body().string();

    } catch (Exception e) {
        throw new ApiException("Problem communicating with API", e);
    }
}