Jetty ResourceCache 与 CachedContentFactory

Jetty ResourceCache vs CachedContentFactory

我正在从 Jetty 9.0.x 迁移到 9.4.x

org.eclipse.jetty.server.ResourceCache 已从 Jetty 9.4.x

中移除

问题:

1) 9.4.x 中这个 class 的替代品是什么?

2) 我发现 CachedContentFactory 是这个 class 最接近的等价物,但是这个 class 的构造函数需要一个额外的参数 CompressedContentFormat[] precompressedFormats。如果这是一个正确的替换,那么我不确定我应该为这个参数传递什么?它可以是空数组吗?抱歉,javadocs 也没有太大帮助。

首先是一些历史。

在主要版本 Jetty 9.0.0 期间,有两种处理静态内容的主要方法: DefaultHandler(还有劣等的ResourceHandler)。

当主要版本 Jetty 9.4.0 推出时(这是 Jetty 9.0.0 之后的 4 个主要版本),努力使这两个组件使用通用代码库,因此 ResourceService 的创建是为了在一个地方标准化静态内容的服务。现在 DefaultHandlerResourceHandler 之间的差异大大减少了。 (注意:DefaultHandler 仍然支持其自身的更多功能以及各种 HTTP 规范的更多功能

接下来,Issue #539 已解决以允许 ResourceHandler(现在是 DefaultHandler)拥有自定义目录列表。为此,引入了 HttpOutput.ContentFactory 界面。

新的 HttpOutput.ContentFactory 负责返回表示所提供路径的 HttpContent(以及可选的最大缓冲区大小配置选项)。

这意味着,此时我们有...

  1. 一个DefaultServlet(或ResourceHandler
  2. 其中有一个ResourceService
  3. 它从 HttpOutput.ContentFactory
  4. 中获取内容
  5. 返回的HttpContent可以是静态资源、目录列表或欢迎文件。

当需要发送一段静态内容时,所采取的步骤是...

  1. HttpOutput.ContentFactory.getContent(path, maxBufferSize)
  2. 请求 HttpContent 对象
  3. 请求可用于发送引用内容的 HttpContent 表示,以下之一(按此顺序):
    1. 如果HttpChannel配置为使用"direct buffers",则要求HttpContent.getDirectBuffer()代表全部内容。 (这可能是一个内存映射文件,使用的堆内存量可以忽略不计)
    2. 要求 HttpContent.getIndirectBuffer() 代表全部内容。 (这可能是一个内存映射文件,使用的堆内存量可以忽略不计)
    3. 请求 HttpContent.getReadableByteChannel() 发送内容。
    4. 要求 HttpContent.getInputStream() 发送内容。
  4. Return 错误指示 "Unknown Content"

Jetty 9.4.0+

中有 2 个 HttpOutput.ContentFactory 的主要实现
  • ResourceContentFactory 处理临时内容(未缓存)- 如果内容超过 maxBufferSize,则不会返回原始 ByteBuffer 版本。
  • CachedContentFactory 将缓存以前 HttpOutput 用法返回的各种 ByteBuffer 值。

CachedContentFactory 有一个 isCacheable(Resource) 方法,该方法被询问以了解提供的资源是否应该进入 in-memory 缓存。

关于CachedContentFactory构造函数中的CompressedContentFormat[] precompressedFormats参数,指的是ResourceServiceCachedContentFactory都支持的"pre-compressed"格式.

典型的默认设置是...

CompressedContentFormat[] precompressedFormats = {
    CompressedContentFormat.GZIP, // gzip compressed
    CompressedContentFormat.BR, // brotli compressed
    new CompressedContentFormat("bzip", ".bz") // bzip compressed
};
CachedContentFactory cachedContentFactory = new CachedContentFactory(parentContentFactory,
   resourceFactory, mimeTypes, useFileMappedBuffers,
   useEtags, precompressedFormats);
resourceService.setContentFactory(cachedContentFactory);

这些precompressedFormats指的是在服务器启动之前已经预压缩的静态(和不可变)内容。

这允许客户端发送请求说...

GET /css/main.css HTTP/1.1
Host: example.hostname.com
Accept-Encoding: gzip, deflate

并且如果 "Base Resource" 目录有 ${resource.basedir}/css/main.css AND ${resource.basedir}/css/main.css.gz 那么响应将从 main.css.gz(不是 main.css),导致像 ...

这样的 HTTP 响应
HTTP/1.1 200 OK
Date: Wed, 15 May 2019 20:17:22 GMT
Vary: Accept-Encoding
Last-Modified: Wed, 15 May 2019 20:17:22 GMT
Content-Type: text/css
ETag: W/"H/6qTDwA8vsH/6rJoEknqc"
Accept-Ranges: bytes
Content-Length: 11222