我正在通过参考this one来编写一个非常简单的代理servlet。我想要o添加缓存功能,其中缓存中的键将是URI。
当然,问题在于我无法缓存整个响应,因为如果我将其传递通过管道,则输入流将被消耗,然后缓存的响应将不再可用。
您认为解决此问题的最佳方法是什么?如何在不消耗HTTPResponse内容的情况下复制HTTPResponse(或仅HTTPEntity)?
答案 0 :(得分:1)
除非另有说明,否则InputStream
是单次拍摄:您只需消费一次即可。
如果您想多次阅读它,那就不再是流了,而是带有缓冲区的流。要缓存输入流,您应该将响应内容写入文件或内存中,以便可以再次(多次)重新读取。
HTTPEntity
可以重新读取,但这取决于实现的类型。例如,您可以使用.isRepeatable()
进行检查。这是apache的原始javadoc。
流式传输:内容是从流中接收的,或者是即时生成的。特别地,该类别包括从连接接收的实体。流式实体通常不可重复。
自包含:内容位于内存中或通过独立于连接或其他实体的方式获得。独立的实体通常是可重复的。
包装:内容是从另一个实体获得的。
您可以使用自包含的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缓存。
https://hc.apache.org/httpcomponents-client-ga/tutorial/html/caching.html