0

我正在编写一个非常简单的代理 servlet,以此作为参考。我想添加缓存功能,其中缓存中的键是 URI。

当然,问题是我无法缓存整个响应,因为如果我将它通过管道传递,输入流将被消耗,然后缓存的响应不再可用。

您认为解决此问题的最佳方法是什么?如何在不消耗内容的情况下复制 HTTPResponse(或只是 HTTPEntity)?

4

1 回答 1

1

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

于 2019-05-14T11:33:35.410 回答