如何为Jetty9启用gzip压缩(静态和动态)?

4
我使用Jetty9,想要测试压缩文本文件是否会提高性能。首先,我对像这个链接描述的离线压缩文件进行服务感兴趣:http://marianoguerra.org/posts/201205enable-gzip-compression-in-jetty.html 我的代码如下:
static private void set_jetty_handlers(Server server)
    {
    // gzip: I have added it to to serve off-line compressed JavaScript, CSS etc.
    // as described at: http://marianoguerra.org/posts/201205enable-gzip-compression-in-jetty.html
    ServletHolder servletHolder = new ServletHolder(new DefaultServlet());
    servletHolder.setInitParameter("gzip", "true");
    ServletContextHandler s_context_handler = new ServletContextHandler();
    s_context_handler.addServlet(servletHolder,"/*");

    ResourceHandler resource_handler = new ResourceHandler();
    resource_handler.setDirectoriesListed(false);
    resource_handler.setWelcomeFiles(new String[] {"index.html"});
    resource_handler.setResourceBase("");
    resource_handler.setCacheControl(MAX_AGE);

    // gzip: I have added it to to serve offline compressed JavaScript, CSS etc.
    resource_handler.setHandler(s_context_handler);

    // I want to work with aliases (links and symbolic links)
    ContextHandler context_handler = new ContextHandler();
    context_handler.addAliasCheck(new ContextHandler.ApproveAliases());

    HandlerList handlers = new HandlerList();
    handlers.setHandlers(new Handler[] { new my_jetty_handler(), resource_handler, new DefaultHandler() });
    context_handler.setHandler(handlers);

    server.setHandler(context_handler);
    configureThreadPool(server);
    } // set_jetty_handlers

当我将test.html压缩成test.html.gz时,我收到了HTTP ERROR: 404的错误消息。我在注释中使用gzip:标记添加了启用gzip压缩所需的代码行。
我还发现较早版本的Jetty有一个ResourceHandler.setMinGzipLength()方法,但在当前版本中不可用,但根据文档,它能实现我的需求。
如何启用gzip压缩?起初,我想测试静态文件压缩,但经过这些测试后,我想在my_jetty_handler()中应用GzipFilter以提供动态内容,但从Java代码中如何实现还不清楚。
2个回答

5

我可以通过以下方式为我的处理程序添加gzip压缩:

GzipHandler gzipHandlerRES = new GzipHandler();
gzipHandlerRES.setMimeTypes("text/html,text/plain,text/xml,text/css,application/javascript,text/javascript");
gzipHandlerRES.setHandler(resource_handler);

它不能处理离线压缩文件(请求 test.html 应该返回 test.html.gz)。


2
然后,您需要将gzipHandlerRES添加到Server.setHandler(Handler)数组中。 - Julien Kronegg

1
你的行为有些混乱,对上下文的理解也不够清晰。首先看一下这个例子:
package jetty;

import java.util.EnumSet;

import javax.servlet.DispatcherType;

import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.servlet.DefaultServlet;
import org.eclipse.jetty.servlet.FilterHolder;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jetty.servlets.GzipFilter;
import org.eclipse.jetty.util.thread.QueuedThreadPool;
import org.eclipse.jetty.util.thread.ThreadPool;

public class GzipExample
{
    public static void main(String[] args)
    {
        ThreadPool threadPool = new QueuedThreadPool();
        Server server = new Server(threadPool);
        ServerConnector connector = new ServerConnector(server);
        connector.setPort(8080);
        server.addConnector(connector);

        ServletContextHandler context = new ServletContextHandler();
        context.setContextPath("/");
        // Welcome files are part of the context
        context.setWelcomeFiles(new String[] { "index.html" });
        // Add alias check logic to context
        context.addAliasCheck(new ContextHandler.ApproveAliases());
        server.setHandler(context);

        // Add dynamic Gzip compression, as a servlet filter
        FilterHolder gzipHolder = context.addFilter(GzipFilter.class,"/*",EnumSet.of(DispatcherType.REQUEST));
        gzipHolder.setInitParameter("methods","GET,POST");
        // response bytes required before gzip kicks in 
        gzipHolder.setInitParameter("minGzipSize", "256");
        // mime-types to compress (seen as response type)
        gzipHolder.setInitParameter("mimeTypes", "text/plain,text/css,text/html,text/javascript");

        // Add your own servlets here
        context.addServlet(HelloServlet.class,"/hello/*");

        // Lastly, the default servlet for resource base content (serves static files)
        // It is important that this is last.
        ServletHolder defHolder = new ServletHolder("default", DefaultServlet.class);
        // Cannot be null or empty, must be declared, must be a directory, can be a URL to some jar content
        defHolder.setInitParameter("resourceBase","./resource-base/");
        defHolder.setInitParameter("dirAllowed","true");
        defHolder.setInitParameter("gzip", "true");
        defHolder.setInitParameter("otherGzipFileExtensions", ".svgz");
        defHolder.setInitParameter("cacheControl","private, max-age=0, no-cache");
        context.addServlet(defHolder,"/");
    }
}

重要的是什么:
  • 线程池被设置并提供给服务器实例,而不是事后配置。
  • ServletContextHandler 是你的上下文,它包含欢迎文件列表、上下文路径名称、别名检查、所有过滤器和servlet。
  • GzipFilter 是目前设置动态gzip压缩的方式(在Jetty 9.3.x中将更改为更基本的gzip处理机制,更能适应http/2 +异步I/O现实)。
  • GzipFilter 配置了gzip行为,包括压缩的最小字节阈值、mime类型等...
  • DefaultServlet 是用于提供静态文件的组件,包括支持可选的预压缩静态文件。(例如:客户端请求/main.css,表示它能够接收gzip压缩的文件,default servlet在资源库中找到/main.css.gz并按原样返回给请求/main.css的客户端。)
  • resourceBase 是所有这些工作所必需的,需要定义它。
  • ResourceHandler 极为基础,不适用于高级概念,如gzip、缓存、恢复、部分/范围请求等...
  • 不能使用Jetty Handlers进行gzip压缩,这只是作为servlet层的一部分实现。(这将在最终的Jetty 9.3.0版本中更改)

1
谢谢。是的,我混合了行为,因为我没有使用servlets。我为某些请求使用自己的处理程序和ResourceHandler用于静态文件。我专门添加了ServletContext以进行gzip压缩。我不知道如何将我的处理程序添加到您的解决方案中的servlet上下文中。我尝试了各种方法,但都失败了。 - Michał Niklas

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接