【问题标题】:Jetty-servlets GzipFilter doesn't work with Jetty 9.2.7.v20150116 and SpringJetty-servlets GzipFilter 不适用于 Jetty 9.2.7.v20150116 和 Spring
【发布时间】:2017-01-05 13:34:35
【问题描述】:

我在 web.xml 文件中使用以下 xml 将 GzipFilter 配置到我使用 Jetty 运行的 Spring 应用程序中。在使用 Chrome 中的开发人员工具进行检查时,我希望看到资源大小变得更小,并且我希望在响应标头中看到“编码”具有值“gzip”。但是,这些都不是可见的。

但是,在我的 IDE 中使用调试工具进行检查时,我注意到过滤器已被应用(我将断点置于 GzipFilter),并且在使用开发人员工具检查时,我注意到 etag-headers 在响应中具有 -gzip 扩展名.但是内容似乎没有被压缩。

我的想法已经不多了,希望能提供任何帮助。

<filter>
  <filter-name>GzipFilter</filter-name>
  <filter-class>org.eclipse.jetty.servlets.GzipFilter</filter-class>
  <init-param>
     <param-name>mimeTypes</param-name>
     <param-value>text/html,text/plain,text/xml,application/xhtml+xml,text/css,application/javascript,application/json,image/svg+xml</param-value>
  </init-param>
</filter>
<filter-mapping>
  <filter-name>GzipFilter</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>

编辑:添加请求和响应标头

 Request:
 GET ******* HTTP/1.1
 Host: localhost:8081
 Connection: keep-alive
 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6)       AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36
 Accept: */*
 Referer: http://localhost:8081/
 Accept-Encoding: gzip, deflate, sdch
 Accept-Language: en-US,en;q=0.8,fi;q=0.6
 Cookie: XSRF-TOKEN=******; JSESSIONID=*******

 Response:
 HTTP/1.1 200 OK
 Date: Mon, 29 Aug 2016 13:59:59 GMT
 Cache-Control: public
 Date: Mon, 29 Aug 2016 13:59:59 GMT
 Content-Type: application/javascript;charset=UTF-8
 Vary: Accept-Encoding, User-Agent
 ETag: "0f93db3b42f19c57f4a216dd80f63bae5--gzip"
 Server: Jetty(9.2.7.v20150116)
 Transfer-Encoding: chunked

【问题讨论】:

  • 编辑您的问题并包含其中一个失败请求的请求标头 + 响应标头。

标签: spring servlets jetty gzip


【解决方案1】:

GzipFilter 使用ETag 上的--gzip 后缀来了解请求处理是否实际通过GzipFilter

如果请求曾经被 gzip 压缩,现在不再被 gzip 压缩,其目的是打破 DefaultServlet 中的 ETag 支持。

意思是这个流程:

  • 使用 gzip 配置的服务器
  • 请求资源/foo.js
  • DefaultServlet 使用ETag: abcdef/foo.js 发送响应
  • GzipFilter 配置为压缩application/javascript,因此它压缩了响应并将ETag 更改为ETag: abcdef--gzip
  • 一段时间后,GzipFilter 被重新配置(不同的 url 模式、不同的 mime 类型等等)
  • 相同的用户代理请求资源 /foo.jsETag: abcdef--gzip,但这不再通过 GzipFilter,因此 DefaultServlet 将无法识别 ETag 并重新提供内容。

至于为什么你的内容没有被压缩,要么是因为你设置response.setContentType()的方式,要么是响应正文内容的大小。

首先,您需要确保在访问响应输出流(或写入器)之前始终设置响应状态代码、响应标头和(可选)响应缓冲区大小,因为.getOutputStream().getWriter() 都使用来自响应对象的值来设置自己。

GzipFilter 也使用这些值来判断响应是否应该被压缩。

接下来,响应正文内容的大小很重要,因为在 GzipFilter 参与之前,响应大小有一个下限。 (压缩GzipFilter.minGzipSize以下的大部分内容实际上效率很低)

在您的 Jetty 版本中,我相信 minGzipSize 是 256 字节。

由于您粘贴的响应标头没有 Content-LengthTransfer-Encoding: chunked,因此我无法判断您的响应实际上有多大。

重要的升级说明:Jetty 9.3+ 中的 GzipFilter 已完全弃用,如果使用会导致无操作。这是因为在使用 Servlet 3.1 和 Async I/O 时,用于 Gzip 压缩的过滤器方法存在很大问题。

Jetty 9.3+ 中的 Gzip 支持已移至 Servlet 规范之外并进入低级别 HttpOutput.Interceptor 模式,该模式仅在刷新发生后压缩内容(自动内部或指定应用程序)。

换一种说法,servlet 缓冲区在从应用程序写入 servlet 缓冲区时不会被压缩,就像在 Jetty 9.2 和之前的版本中一样。相反,它们仅在离开 servlet 缓冲区并进入网络级写入时才被压缩。

【讨论】:

    猜你喜欢
    • 2011-11-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-08
    • 1970-01-01
    相关资源
    最近更新 更多