Which compression (is GZIP the most popular) servlet filter would you suggest?

后端 未结 5 1150
一生所求
一生所求 2020-11-29 03:40

I am looking for a GZIP servlet filter to be used in a high volume web-app. I doesn\'t want to use the container specific options.

Requirement

  1. Ability
相关标签:
5条回答
  • 2020-11-29 04:06

    The GZIP filter that I use to compress resources in my webapps:

    public class CompressionFilter implements Filter {
    
        public void destroy() {
        }
    
        public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
            HttpServletRequest httpRequest = (HttpServletRequest) request;
            HttpServletResponse httpResponse = (HttpServletResponse) response;
            String acceptEncoding = httpRequest.getHeader(HttpHeaders.ACCEPT_ENCODING);
            if (acceptEncoding != null) {
                if (acceptEncoding.indexOf("gzip") >= 0) {
                    GZIPHttpServletResponseWrapper gzipResponse = new GZIPHttpServletResponseWrapper(httpResponse);
                    chain.doFilter(request, gzipResponse);
                    gzipResponse.finish();
                    return;
                }
            }
            chain.doFilter(request, response);
        }
    
        public void init(FilterConfig filterConfig) throws ServletException {
        }
    
    }
    
    public class GZIPHttpServletResponseWrapper extends HttpServletResponseWrapper {
    
        private ServletResponseGZIPOutputStream gzipStream;
        private ServletOutputStream outputStream;
        private PrintWriter printWriter;
    
        public GZIPHttpServletResponseWrapper(HttpServletResponse response) throws IOException {
            super(response);
            response.addHeader(HttpHeaders.CONTENT_ENCODING, "gzip");
        }
    
        public void finish() throws IOException {
            if (printWriter != null) {
                printWriter.close();
            }
            if (outputStream != null) {
                outputStream.close();
            }
            if (gzipStream != null) {
                gzipStream.close();
            }
        }
    
        @Override
        public void flushBuffer() throws IOException {
            if (printWriter != null) {
                printWriter.flush();
            }
            if (outputStream != null) {
                outputStream.flush();
            }
            super.flushBuffer();
        }
    
        @Override
        public ServletOutputStream getOutputStream() throws IOException {
            if (printWriter != null) {
                throw new IllegalStateException("printWriter already defined");
            }
            if (outputStream == null) {
                initGzip();
                outputStream = gzipStream;
            }
            return outputStream;
        }
    
        @Override
        public PrintWriter getWriter() throws IOException {
            if (outputStream != null) {
                throw new IllegalStateException("printWriter already defined");
            }
            if (printWriter == null) {
                initGzip();
                printWriter = new PrintWriter(new OutputStreamWriter(gzipStream, getResponse().getCharacterEncoding()));
            }
            return printWriter;
        }
    
        @Override
        public void setContentLength(int len) {
        }
    
        private void initGzip() throws IOException {
            gzipStream = new ServletResponseGZIPOutputStream(getResponse().getOutputStream());
        }
    
    }
    
    public class ServletResponseGZIPOutputStream extends ServletOutputStream {
    
        GZIPOutputStream gzipStream;
        final AtomicBoolean open = new AtomicBoolean(true);
        OutputStream output;
    
        public ServletResponseGZIPOutputStream(OutputStream output) throws IOException {
            this.output = output;
            gzipStream = new GZIPOutputStream(output);
        }
    
        @Override
        public void close() throws IOException {
            if (open.compareAndSet(true, false)) {
                gzipStream.close();
            }
        }
    
        @Override
        public void flush() throws IOException {
            gzipStream.flush();
        }
    
        @Override
        public void write(byte[] b) throws IOException {
            write(b, 0, b.length);
        }
    
        @Override
        public void write(byte[] b, int off, int len) throws IOException {
            if (!open.get()) {
                throw new IOException("Stream closed!");
            }
            gzipStream.write(b, off, len);
        }
    
        @Override
        public void write(int b) throws IOException {
            if (!open.get()) {
                throw new IOException("Stream closed!");
            }
            gzipStream.write(b);
        }
    
    }
    

    You also need to define the mapping in your web.xml:

    <filter>
        <filter-name>CompressionFilter</filter-name>
        <filter-class>com.my.company.CompressionFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>CompressionFilter</filter-name>
        <url-pattern>*.js</url-pattern>
    </filter-mapping>
    <filter-mapping>
        <filter-name>CompressionFilter</filter-name>
        <url-pattern>*.css</url-pattern>
    </filter-mapping>
    <filter-mapping>
        <filter-name>CompressionFilter</filter-name>
        <url-pattern>*.html</url-pattern>
    </filter-mapping>
    <filter-mapping>
        <filter-name>CompressionFilter</filter-name>
        <url-pattern>*.jsp</url-pattern>
    </filter-mapping>
    
    0 讨论(0)
  • 2020-11-29 04:08

    I would recommend you use something in-front of tomcat to off-load gzipping. Apache with mod_deflate will perform well. You have the option of putting apache on the same box, or moving it off to a different box, that way compression doesn't impact your app at all. mod_jk or mod_proxy will both work fine in this setup.

    http://httpd.apache.org/docs/2.0/mod/mod_deflate.html

    0 讨论(0)
  • 2020-11-29 04:10

    From what i've seen, most people generally use the gzip compression filter. Typically from ehcache.

    The GZIP filter implementation is: net.sf.ehcache.constructs.web.filter.GzipFilter

    The Maven coordinate for including it in your project is:

    <dependency>
        <groupId>net.sf.ehcache</groupId>
        <artifactId>ehcache-web</artifactId>
        <version>2.0.4</version>
    </dependency>
    

    You will also need to specify an SLF4J logging target. If you don't know what this is or don't care slf4j-jdk14 or slf4j-simple works:

    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-jdk14</artifactId>
        <version>1.6.4</version>
    </dependency>
    
    0 讨论(0)
  • 2020-11-29 04:14

    Or if you're using Nginx in front see here: http://nginx.org/en/docs/http/ngx_http_gzip_module.html. But definitely, as Zeki said it is better to move this to the dedicated web server.

    0 讨论(0)
  • 2020-11-29 04:28

    Check out the pjl-comp-filter CompressingFilter:

    http://sourceforge.net/projects/pjl-comp-filter/

    0 讨论(0)
提交回复
热议问题