简体   繁体   中英

How to enable gzip compression (both static and dynamic) for Jetty9?

I use Jetty9 and I want to test if compressing text files will increase performance. At first I'm interested in serving off-line compressed files just like it is described at: http://marianoguerra.org/posts/201205enable-gzip-compression-in-jetty.html

My code looks like:

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

But when I compressed test.html into test.html.gz then I got HTTP ERROR: 404 . Lines I added to enable gzip compression are tagged with gzip: in comment.

I have also found that older version of Jetty had ResourceHandler.setMinGzipLength() . It is not available in current Jetty version but from documentation it does what I want.

How to enable gzip compression? At first I want to test static files compression, but after those tests I want to apply GzipFilter in my my_jetty_handler() that serves dynamic content and is also unclear how to do it from Java code.

I can add gzip compression for my handlers by:

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

It cannot work with offline compressed files (request for test.html should serve test.html.gz ).

You have a mix of behavior, and a broken understanding of how contexts work.

First, the example:

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,"/");
    }
}

What's important:

  • ThreadPool is setup and provided to the Server instance, not configured after the fact.
  • ServletContextHandler is your context, it holds the welcome files list, the name of your context path, the alias check, all of your filters and servlets.
  • GzipFilter is the way currently (this is changing in Jetty 9.3.x to a more fundamental gzip handling mechanism that is more resilient to http/2 + async i/o realities) to setup dynamic gzip compression.
  • GzipFilter has configuration for the gzip behavior, including minimum byte threshold for compression, mime-types, etc ...
  • DefaultServlet is the component that serves your static files, including support to serve optionally pre-compressed static files. (eg: client requests /main.css , indicating it is capable of receiving gzip compressed, the default servlet finds /main.css.gz in your resource base and serves it back as-is, to the client requesting /main.css )
  • resourceBase is required for all of this to work, define it.
  • ResourceHandler is super basic, and isn't meant for advanced concepts like gzip, caching, resume, partial/range request, etc...
  • You cannot use Jetty Handlers with gzip compression, that's only implemented as part of the servlet layer. (this will change with the final Jetty 9.3.0 release)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM