代码之家  ›  专栏  ›  技术社区  ›  jacobq

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

  •  1
  • jacobq  · 技术社区  · 11 年前

    我正在使用 CachingHttpClientBuilder 创建 CloseableHttpClient 中的 HttpServlet 以获取内部资源。在大多数情况下,我希望它使用它的缓存,这似乎很好。但是,定期使用客户端检查特定远程文件的更新(基本上它有配置数据)。在这种情况下,我希望能够告诉客户机通过HTTP获取资源,即使缓存中包含该资源,并且该资源尚未标记为过时。

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

    以免有人建议只更改远程服务器 Cache-Control: no-cache 为了防止这种情况,请理解这是我无法控制的。目标是绕过此实例中的缓存,而不管远程服务器是否表示可以/应该缓存缓存。

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

    编辑 :user3360944建议使用 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 回复  |  直到 11 年前
        1
  •  1
  •   ok2c    11 年前

    它将涉及一些自定义代码,但可以通过稍微调整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();
    
        2
  •  1
  •   user3360944    11 年前

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

    setHttpCacheInvalidator(HttpCacheInvalidator cacheInvalidator) 
    

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