Jetty 8 GzipFilter 有时不适用

Posted

技术标签:

【中文标题】Jetty 8 GzipFilter 有时不适用【英文标题】:Jetty 8 GzipFilter does not apply sometimes 【发布时间】:2011-11-22 18:10:10 【问题描述】:

我刚刚将我的网络服务器从 Jetty 6.x 更新到 Jetty 8.0.1,出于某种原因,当我执行完全相同的请求时,有时响应已被 Gzip 压缩,有时则没有。

下面是 servlet 的 service() 方法开头的请求和响应的样子:

Request: [GET /test/hello_world?param=test]@11538114 org.eclipse.jetty.server.Request@b00ec2
Response: org.eclipse.jetty.servlets.GzipFilter$2@1220fd1
WORKED!

Request:[GET /test/hello_world?param=test]@19386718 org.eclipse.jetty.server.Request@127d15e
Response:HTTP/1.1 200 
Connection: close
FAILED!

这是我的 GzipFilter 声明:

EnumSet<DispatcherType> all = EnumSet.of(DispatcherType.ASYNC, DispatcherType.ERROR, DispatcherType.FORWARD,
            DispatcherType.INCLUDE, DispatcherType.REQUEST);
FilterHolder gzipFilter = new FilterHolder(new GzipFilter());
gzipFilter.setInitParameter("mimeTypes", "text/javascript");
gzipFilter.setInitParameter("minGzipSize", "0");
context.addFilter(gzipFilter, "/test/*", all);

Javadoc 说:

GZIP Filter This filter will gzip the content of a response if:
    The filter is mapped to a matching path ==>
    The response status code is >=200 and <300
    The content length is unknown or more than the minGzipSize initParameter or the minGzipSize is 0(default)
    The content-type is in the comma separated list of mimeTypes set in the mimeTypes initParameter or if no mimeTypes are defined the content-type is not "application/gzip"
    No content-encoding is specified by the resource

在我看来,所有这些条件都满足,除了最后一个“资源未指定内容编码”。如何验证?

另外,出于我也忽略的原因,当未使用 GzipFilter 过滤响应时,response.getWriter() 会引发 IO 异常。这是为什么呢?

【问题讨论】:

【参考方案1】:

我遇到了同样的问题,找到了2个原因:

    如果您的任何 servlet 过早调用 response.getWriter().flush(),GZipFilter 将无法工作。在我的例子中,Spring MVC 中的 Freemarker 和 Sitemesh 都在这样做,因此我必须将 Freemarker servlet 和 Spring MVC Freemarker 配置对象的 Freemarker 设置“auto_flush”设置为“false”。 如果您使用普通的 GzipFilter,由于某种原因,它不允许您在 Jetty 的“包含”阶段设置任何标题。所以我不得不改用IncludableGzipFilter。

进行这些更改后,它对我有用。希望对你也有帮助。

【讨论】:

【参考方案2】:

您可以使用另一个 GzipFilter。将其添加到您的 maven 或下载 jar 文件http://mvnrepository.com/artifact/net.sourceforge.pjl-comp-filter/pjl-comp-filter/1.7

然后只需更改您的代码:

EnumSet<DispatcherType> all = EnumSet.of(DispatcherType.ASYNC,     DispatcherType.ERROR, DispatcherType.FORWARD, DispatcherType.INCLUDE, DispatcherType.REQUEST);
FilterHolder gzipFilter = new FilterHolder(new CompressingFilter());
gzipFilter.setInitParameter("includeContentTypes", "text/javascript");
context.addFilter(gzipFilter, "/test/*", all);

我遇到了同样的问题,这解决了问题。

【讨论】:

【参考方案3】:

我可以建议您使用Fiddler 来跟踪您的 HTTP 请求吗?

也许,像Last-Modified 这样的标头向您的浏览器表明您的请求内容/test/hello_world?param=test 仍然相同...因此您的浏览器会重用缓存中的内容并简单地关闭请求,而不读取其内容...

两个不同的请求会发生什么?

/test/hello_world?param=test /test/hello_world?param=test&amp;foo=1

【讨论】:

以上是关于Jetty 8 GzipFilter 有时不适用的主要内容,如果未能解决你的问题,请参考以下文章

Filter拦截器

使用maven jetty插件在java 8上运行jetty 9时出现错误扫描文件[重复]

jetty 支持内嵌ssh项目吗,为啥在tomcat下面正常的war 放到jetty就跑不起来

使用 JSR-356(websockets)的 Jetty 8 配置

Jetty 8.1.1 Websocket 客户端握手

xwiki enterprise 8.4.5使用https步骤