我正在编写一个非常简单的代理 servlet,以此作为参考。我想添加缓存功能,其中缓存中的键是 URI。
当然,问题是我无法缓存整个响应,因为如果我将它通过管道传递,输入流将被消耗,然后缓存的响应不再可用。
您认为解决此问题的最佳方法是什么?如何在不消耗内容的情况下复制 HTTPResponse(或只是 HTTPEntity)?
我正在编写一个非常简单的代理 servlet,以此作为参考。我想添加缓存功能,其中缓存中的键是 URI。
当然,问题是我无法缓存整个响应,因为如果我将它通过管道传递,输入流将被消耗,然后缓存的响应不再可用。
您认为解决此问题的最佳方法是什么?如何在不消耗内容的情况下复制 HTTPResponse(或只是 HTTPEntity)?
InputStream
除非另有说明,否则An是单发的:您使用一次,仅此而已。
如果您想多次阅读它,那不再只是一个流,而是一个带有缓冲区的流。要缓存输入流,您应该将响应内容写入文件或内存中,以便您可以再次(多次)重新读取它。
可以重新读取,HTTPEntity
但这取决于实现的类型。例如,您可以检查这一点.isRepeatable()
。这是 apache 的原始 javadoc。
streamed:内容是从流中接收的,或者是动态生成的。特别是,此类别包括从连接接收的实体。流式实体通常是不可重复的。
自包含:内容在内存中或通过独立于连接或其他实体的方式获得。自包含实体通常是可重复的。
wrapping:内容是从另一个实体获取的。
您可以使用FileEntity
它是独立的,因此是可重复的(重新可读)。
要存档此文件(缓存到文件中),您可以读取内容HTTPEntity
并将其写入File
. 之后,您可以使用我们之前创建和编写FileEntity
的, 创建一个。File
最后,您只需将HTTPResponse
' 实体替换为新的FileEntity
.
这是一个没有上下文的简单示例:
// Get the untouched entity from the HTTPResponse
HttpEntity originalEntity = response.getEntity();
// Obtain the content type of the response.
String contentType = originalEntity.getContentType().getElements()[0].getValue();
// Create a file for the cache. You should hash the the URL and pass it as the filename.
File targetFile = new File("/some/cache/folder/{--- HERE the URL in HASHED form ---}");
// Copy the input stream into the file above.
FileUtils.copyInputStreamToFile(originalEntity.getContent(), targetFile);
// Create a new Entity, pass the file and the replace the HTTPResponse's entity with it.
HttpEntity newEntity = new FileEntity(targetFile, ContentType.getByMimeType(contentType));
response.setEntity(newEntity);
现在您可以在以后一次又一次地从文件中重新读取内容。
您只需要根据 URI 找到文件 :)
要在内存中缓存,您可以使用ByteArrayEntity
.
此方法只是缓存正文。不是http标头。
或者您可以使用Apache HttpClient Cache。
https://hc.apache.org/httpcomponents-client-ga/tutorial/html/caching.html