有没有一种简单的方法来手动强制缓存HttpClient 4.3.x绕过缓存?

时间:2014-03-07 16:47:40

标签: java apache-httpclient-4.x

我正在使用CachingHttpClientBuilder通过HttpServlet创建CloseableHttpClient来获取内部资源。在大多数情况下,我希望它使用它的缓存,这似乎工作正常。但是,定期使用客户端检查特殊远程文件的更新(基本上它具有配置数据)。在这种情况下,我希望能够告诉客户端通过HTTP获取资源,即使缓存包含它并且它还没有被标记为陈旧。

当我在JavaScript中遇到这样的情况时,我经常附加一个伪造的查询字符串参数,其中包含时间戳,以便URL与缓存的条目不匹配。但是,我认为在这种情况下有更好的解决方案,因为我们可以直接以编程方式访问HTTP客户端。

为了避免有人建议只更改远程服务器,以便设置Cache-Control: no-cache标头以防止这种情况,请理解这是我无法控制的。目标是在此实例中绕过缓存,无论远程服务器是否说它可以/应该缓存。

有人可能还建议在这种情况下不使用缓存HttpClient,这样就行了,但对我来说似乎不太理想,因为那时我需要再做一次HttpClient(其他部分)此应用程序需要缓存这些HTTP资源才能充分执行。

编辑:用户3360944建议使用HttpCacheInvalidator,这可能是正确的解决方案,但我不确定如何执行此操作。有人可以举例说明在flushInvalidatedCacheEntries方法中放置什么来删除给定URL的缓存条目吗? (我有特殊的URL,我从不想缓存)

new HttpCacheInvalidator() {
    @Override
    public void flushInvalidatedCacheEntries(HttpHost host, HttpRequest req) {
        // What do I need to do here to invalidate a cached entry for
        // say, http://www.example.com/path/file.txt?
    }

    @Override
    public void flushInvalidatedCacheEntries(HttpHost host, HttpRequest request, HttpResponse response) {        
        // Do nothing here since I don't need to invalidate anything
        // based on the response received
    }
}

2 个答案:

答案 0 :(得分:1)

由于您拥有CachingHttpClientBuilder,您可以将其配置为使用此方法使用特定的HttpCacheInvalidator

setHttpCacheInvalidator(HttpCacheInvalidator cacheInvalidator) 

如果您需要未缓存版本的响应,可以使用HttpCachedInvalidator在发出请求之前使请求无效。

答案 1 :(得分:1)

它将涉及一些自定义代码,但可以通过略微调整HttpClient的执行管道来完全绕过缓存层

class ConditionalCachingExec implements ClientExecChain {

    private final ClientExecChain mainExec;
    private final ClientExecChain cachingExec;

    public ConditionalCachingExec(final ClientExecChain mainExec, final ClientExecChain cachingExec) {
        this.mainExec = mainExec;
        this.cachingExec = cachingExec;
    }

    @Override
    public CloseableHttpResponse execute(
            final HttpRoute route,
            final HttpRequestWrapper request,
            final HttpClientContext clientContext,
            final HttpExecutionAware execAware) throws IOException, HttpException {
        URI uri = request.getURI();
        if ("/stuff".equals(uri.getPath())) {
            return mainExec.execute(route, request, clientContext, execAware);
        } else {
            return cachingExec.execute(route, request, clientContext, execAware);
        }
    }

};

class MyCachingHttpClientBuilder extends CachingHttpClientBuilder {

    @Override
    protected ClientExecChain decorateMainExec(final ClientExecChain mainExec) {
        ClientExecChain cachingExec = super.decorateMainExec(mainExec);
        return new ConditionalCachingExec(mainExec, cachingExec);
    }

};


CloseableHttpClient httpClient = new MyCachingHttpClientBuilder().build();