Какой фильтр сервлетов (GZIP самый популярный) вы бы предложили? - PullRequest
15 голосов
/ 21 января 2011

Я ищу сервлет-фильтр GZIP для использования в веб-приложении большого объема.Я не хочу использовать параметры, специфичные для контейнера.

Требование

  1. Возможность сжатия полезной нагрузки ответа (XML)
  2. Быстрее
  3. Проверенов производстве для приложений большого объема
  4. Должен быть правильно установлен соответствующий Content-Encoding
  5. переносимый между контейнерами
  6. Опционально может распаковать запрос

Спасибо.

Ответы [ 5 ]

16 голосов
/ 21 января 2011

Из того, что я видел, большинство людей обычно используют фильтр сжатия gzip.Обычно из ehcache .

Реализация фильтра GZIP: net.sf.ehcache.constructs.web.filter.GzipFilter

Координата Mavenдля включения его в ваш проект:

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

Вам также нужно будет указать цель ведения журнала SLF4J.Если вы не знаете, что это такое, или вам все равно, slf4j-jdk14 или slf4j-простые работы:

<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-jdk14</artifactId>
    <version>1.6.4</version>
</dependency>
15 голосов
/ 17 июня 2012

Фильтр GZIP, который я использую для сжатия ресурсов в моих веб-приложениях:

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);
    }

}

Вам также необходимо определить отображение в вашем файле 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>
2 голосов
/ 21 января 2011

Я бы порекомендовал вам использовать что-то перед tomcat для разархивирования разгрузки.Apache с mod_deflate будет работать хорошо.У вас есть возможность поместить apache в тот же ящик или перенести его в другой ящик, чтобы сжатие не влияло на ваше приложение.mod_jk или mod_proxy будут нормально работать в этой настройке.

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

2 голосов
/ 21 января 2011

Проверьте pjl-comp-фильтр CompressingFilter:

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

0 голосов
/ 02 марта 2015

Или, если вы используете Nginx, смотрите здесь: http://nginx.org/en/docs/http/ngx_http_gzip_module.html. Но определенно, как сказал Зеки, лучше перенести это на выделенный веб-сервер.

...