Java Httpclient没有';t正确缓存响应

Java Httpclient没有';t正确缓存响应,java,android,apache-httpclient-4.x,Java,Android,Apache Httpclient 4.x,我正在尝试使用ApacheHttpClient加载带有缓存的图像。请求后,文件被保存,但在重复相同的请求后,它再次开始下载,并将新文件保存为缓存。因此缓存的图像不能重用。不删除 文件名仅因散列而不同 138944846612.000000000000000 1-3f1e8b88.localhost.-images-goods-212250-7841874.jpg 1389449952782.000000000000000 1-5720e341.localhost.-images-goods-21

我正在尝试使用ApacheHttpClient加载带有缓存的图像。请求后,文件被保存,但在重复相同的请求后,它再次开始下载,并将新文件保存为缓存。因此缓存的图像不能重用。不删除

文件名仅因散列而不同
138944846612.000000000000000 1-3f1e8b88.localhost.-images-goods-212250-7841874.jpg
1389449952782.000000000000000 1-5720e341.localhost.-images-goods-212250-7841874.jpg

我想,该图像将被加载一次,并能够显示缓存的图像,即使并没有连接到互联网

这是我的密码

RequestConfig config = RequestConfig.custom()
                .setConnectTimeout(30000)
                .setSocketTimeout(30000)
                .setProxy(getProxy())
                .build();

CacheConfig cacheConfig = CacheConfig.custom()
        .build();

CloseableHttpClient client = CachingHttpClientBuilder.create()
        .setCacheDir(new File("/sdcard/Android/data/com.myapp/cache/"))
        .setCacheConfig(cacheConfig)
        .setDefaultRequestConfig(config)
        .build();

HttpGet request = new HttpGet(imageUri);
HttpCacheContext context = HttpCacheContext.create();
CloseableHttpResponse response = client.execute(request, context);
这是图像响应头

Cache-Control:max-age=604800
Connection:keep-alive
Content-Length:449512
Content-Type:image/jpeg
Date:Sat, 11 Jan 2014 15:03:21 GMT
Expires:Sat, 18 Jan 2014 15:03:21 GMT
Last-Modified:Tue, 12 Jul 2011 19:40:44 GMT

第一个问题是,我每次下载之前都创建了新的httpclient,所以每次都创建了HttpCacheStorage的新实例,这就是文件名不同的原因。
第二,默认的HttpCacheStorage只在LinkedHashMap中存储下载数据的信息,因此每次新启动应用程序cacheStorage后,都不知道上一次启动时缓存的数据。
解决方案是创建自己的HttpCacheStorage,它将缓存的数据保存到文件系统中,并在可以从缓存获得响应时从文件中获取数据

我刚刚在CachintTPClientBuilder-setHttpCacheStorage中添加了一行

CachingHttpClientBuilder.create()
                        .setCacheConfig(cacheConfig)
                        .setHttpCacheStorage(new ImagesCacheStorage(cacheConfig, cacheDir))
                        .setDefaultRequestConfig(config)
                        .build();
import myapp.org.apache.http.client.cache.HttpCacheEntry;
import myapp.org.apache.http.client.cache.HttpCacheUpdateCallback;
import myapp.org.apache.http.impl.client.cache.CacheConfig;
import myapp.org.apache.http.impl.client.cache.ManagedHttpCacheStorage;

public class FileCacheStorage extends ManagedHttpCacheStorage {

    private File mCacheDir;

    public FileCacheStorage(final CacheConfig config, File cacheDir) {
        super(config);
        mCacheDir = cacheDir;
    }

    @Override
    public HttpCacheEntry getEntry(final String url) throws IOException {
        HttpCacheEntry entry = super.getEntry(url);
        if (entry == null) {
            entry = loadCacheEnrty(url);
        }
        return entry;
    }

    @Override
    public void putEntry(final String url, final HttpCacheEntry entry) throws IOException {
        super.putEntry(url, entry);
        saveCacheEntry(url, entry);
    }

    @Override
    public void removeEntry(final String url) throws IOException {
        super.removeEntry(url);
        File cache = getCacheFile(url);
        if (cache != null && cache.exists()) {
            cache.delete();
        }
    }

    @Override
    public void updateEntry(
            final String url,
            final HttpCacheUpdateCallback callback) throws IOException {
        super.updateEntry(url, callback);
        HttpCacheEntry entry = loadCacheEnrty(url);
        if (entry != null) {
            callback.update(entry);
        }
    }

    private void saveCacheEntry(String url, HttpCacheEntry entry) {
        ObjectOutputStream stream = null;
        try {
            File cache = getCacheFile(url);
            stream = new ObjectOutputStream(new FileOutputStream(cache));
            stream.writeObject(entry);
            stream.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private HttpCacheEntry loadCacheEnrty(String url) {
        HttpCacheEntry entry = null;
        File cache = getCacheFile(url);
        if (cache != null && cache.exists()) {
            synchronized (this) {
                ObjectInputStream stream = null;
                try {
                    stream = new ObjectInputStream(new FileInputStream(cache));
                    entry = (HttpCacheEntry) stream.readObject();
                    stream.close();
                } catch (ClassNotFoundException e) {
                    e.printStackTrace();
                } catch (StreamCorruptedException e) {
                    e.printStackTrace();
                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return entry;
    }

    private File getCacheFile(String url) {
        return new File(mCacheDir, MD5.getHash(url));
    }

}
并创建了新的类FileCacheStorage

CachingHttpClientBuilder.create()
                        .setCacheConfig(cacheConfig)
                        .setHttpCacheStorage(new ImagesCacheStorage(cacheConfig, cacheDir))
                        .setDefaultRequestConfig(config)
                        .build();
import myapp.org.apache.http.client.cache.HttpCacheEntry;
import myapp.org.apache.http.client.cache.HttpCacheUpdateCallback;
import myapp.org.apache.http.impl.client.cache.CacheConfig;
import myapp.org.apache.http.impl.client.cache.ManagedHttpCacheStorage;

public class FileCacheStorage extends ManagedHttpCacheStorage {

    private File mCacheDir;

    public FileCacheStorage(final CacheConfig config, File cacheDir) {
        super(config);
        mCacheDir = cacheDir;
    }

    @Override
    public HttpCacheEntry getEntry(final String url) throws IOException {
        HttpCacheEntry entry = super.getEntry(url);
        if (entry == null) {
            entry = loadCacheEnrty(url);
        }
        return entry;
    }

    @Override
    public void putEntry(final String url, final HttpCacheEntry entry) throws IOException {
        super.putEntry(url, entry);
        saveCacheEntry(url, entry);
    }

    @Override
    public void removeEntry(final String url) throws IOException {
        super.removeEntry(url);
        File cache = getCacheFile(url);
        if (cache != null && cache.exists()) {
            cache.delete();
        }
    }

    @Override
    public void updateEntry(
            final String url,
            final HttpCacheUpdateCallback callback) throws IOException {
        super.updateEntry(url, callback);
        HttpCacheEntry entry = loadCacheEnrty(url);
        if (entry != null) {
            callback.update(entry);
        }
    }

    private void saveCacheEntry(String url, HttpCacheEntry entry) {
        ObjectOutputStream stream = null;
        try {
            File cache = getCacheFile(url);
            stream = new ObjectOutputStream(new FileOutputStream(cache));
            stream.writeObject(entry);
            stream.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private HttpCacheEntry loadCacheEnrty(String url) {
        HttpCacheEntry entry = null;
        File cache = getCacheFile(url);
        if (cache != null && cache.exists()) {
            synchronized (this) {
                ObjectInputStream stream = null;
                try {
                    stream = new ObjectInputStream(new FileInputStream(cache));
                    entry = (HttpCacheEntry) stream.readObject();
                    stream.close();
                } catch (ClassNotFoundException e) {
                    e.printStackTrace();
                } catch (StreamCorruptedException e) {
                    e.printStackTrace();
                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return entry;
    }

    private File getCacheFile(String url) {
        return new File(mCacheDir, MD5.getHash(url));
    }

}
正如您所看到的,Apache类的包名带有前缀myapp。我尝试使用originjar文件时出错,我认为这是因为Android中已经存在许多类。所以我合并了apache中的几个jar文件,并用它们制作了一个带有该前缀的jar。如果有更好的解决方案,请告诉我。
希望它能帮助别人。

感谢您展示如何做到这一点。但是,updateEntry()方法无法正常工作。它应该类似于
synchronized(this){HttpCacheEntry existing=getEntry(url);HttpCacheEntry updated=callback.update(existing);putEntry(url,updated);}