Каков наилучший способ GZIP страниц веб-приложения JSF-Seam - PullRequest
2 голосов
/ 11 июня 2009

Я занимаюсь разработкой веб-приложения JSF на Tomcat, планируя использовать Seam в ближайшем будущем и хочу добавить сжатие наших веб-страниц и ресурсов (т. Е. Файлов JavaScript и CSS). Мне известны три метода ответов GZIP в сети Java:

  1. Используйте фильтр Ehcache GZIP: он используется в Appfuse, поэтому он, вероятно, надежен и проверяет, поддерживает ли пользовательский агент GZIP, прежде чем применять его, но, похоже, у него есть проблемы с Seam, который мы будем использовать http://seamframework.org/Community/EHCacheGZipFilterIncompatibleWithSeam.

  2. Используйте pjl-фильтр. Из вопроса stackoverflow: Сжатие Tomcat не добавляет кодировку содержимого: gzip в заголовке , похоже, что нет утечек памяти, но я не знаю, есть ли у него проблемы с Seam или не.

  3. Используйте встроенное сжатие Tomcat - хотя оно может не обеспечивать кодировку содержимого (кажется, что Tomcat 6.0.14 работает нормально, но вы можете предоставить только черный список того, к чему сжатие пользовательских агентов не должно применяться.

Кто-нибудь имеет опыт использования этих методов в среде JSF-Seam? Какое "лучшее" решение?

Спасибо, Glen

Ответы [ 8 ]

4 голосов
/ 23 февраля 2016

Фильтр GZIP значительно сократит начальное время загрузки.
Вы можете дополнительно реализовать cacheFilter для приведения производительности ваших экранов в соответствие с пользовательским интерфейсом на основе JavaScript (https://stackoverflow.com/a/35567540/5076414).
Для компонентов на стороне клиента вы можете использовать Primefaces, который является пользовательским интерфейсом на основе JQuery.

Включить фильтр GZIP в JSF

Просто добавьте это к вашему

web.xml

<filter>
    <filter-name>gzipResponseFilter</filter-name>
    <filter-class>org.omnifaces.filter.GzipResponseFilter</filter-class>
    <init-param>
        <description>The threshold size in bytes. Must be a number between 0 and 9999. Defaults to 150.</description>
        <param-name>threshold</param-name>
        <param-value>150</param-value>
    </init-param>
    <init-param>
        <description>The mimetypes which needs to be compressed. Must be a commaseparated string. Defaults to the below values.</description>
        <param-name>mimetypes</param-name>
        <param-value>
     text/plain, text/html, text/xml, text/css, text/javascript, text/csv, text/rtf,
     application/xml, application/xhtml+xml, application/x-javascript, application/javascript, application/json,
     image/svg+xml, image/gif, application/x-font-woff, application/font-woff2, image/png
 </param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>gzipResponseFilter</filter-name>
    <url-pattern>/*</url-pattern>
    <dispatcher>REQUEST</dispatcher>
    <dispatcher>ERROR</dispatcher>
</filter-mapping>
<error-page>
    <exception-type>java.lang.Throwable</exception-type>
    <location>/</location>
</error-page>   

и следующее к вашему

pom.xml

    <dependency>
        <groupId>org.omnifaces</groupId>
        <artifactId>omnifaces</artifactId>
        <version>1.11</version>
    </dependency>

Как проверить, использует ли мой экран gzip

Чтобы увидеть, что ваш контент уже использует gzip и кеш, в вашем браузере Google Chrome -> щелкните правой кнопкой мыши на экране -> осмотрите -> щелкните вкладку сети -> обновите экран. Нажмите на изображения, значки, таблицы стилей и посмотрите, видите ли вы следующее в заголовке ответа

Content-Encoding:gzip, если статус элемента 200

1 голос
/ 28 июля 2011

Используйте встроенное сжатие Tomcat - хотя оно может не обеспечивать кодировку содержимого (кажется, что Tomcat 6.0.14 работает нормально, но вы можете предоставить только черный список того, к чему сжатие пользовательских агентов не должно применяться.

Я думаю, что вы неверно истолковали проблему, обнаруженную в Сжатие Tomcat не добавляет кодировку содержимого: gzip в заголовке . Эта проблема вызвана использованием Apache HTTPD с mod_jk перед Tomcat, который, в свою очередь, плохо настроен на то, что он не отправляет заголовок Content-Encoding обратно из Tomcat. Эта проблема , а не , вызванная самой Tomcat. Tomcat отлично справляется со своей работой.

Я бы сказал, просто продолжайте встроенное сжатие Tomcat. Это так же просто, как добавить атрибут compression="on" к соединителю HTTP в server.xml. У вас есть рядом с настройкой noCompressionUserAgents и настройкой compressableMimeType. Прочитайте документацию по соединителю HTTP .

1 голос
/ 28 июля 2011

Мы используем JBoss Seam на JBoss AS прокси и балансировку нагрузки позади apache + mod_proxy_ajp с mod_deflate для сжатия исходящего трафика.

Преимущества этой установки

  • много примеров в сети
  • простая настройка / отладка с учетом особенностей различных пользовательских агентов
  • изменение конфигурации во время выполнения (apachectl graceful вместо перезапуска webapp / tomcat для отражения изменений).
1 голос
/ 15 октября 2009

Вы должны попробовать API Jawr

1 голос
/ 11 июня 2009

Как насчет добавления nginx внешнего интерфейса и предоставления ему возможности выполнять сжатие (и кэширование)?

http://wiki.nginx.org/Main

В этом случае принадлежит на serverfalut:)

0 голосов
/ 28 июля 2011

Я доволен фильтром EhCache после некоторого взлома. Вот как это работает:

package myapp;

import net.sf.ehcache.constructs.web.GenericResponseWrapper;
import net.sf.ehcache.constructs.web.ResponseUtil;
import static org.jboss.seam.ScopeType.STATELESS;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.Scope;
import org.jboss.seam.annotations.intercept.BypassInterceptors;
import org.jboss.seam.annotations.web.Filter;

import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.zip.GZIPOutputStream;

/**
 * Zip content before sending to the browser.
 * 
 * 
 */
@Name("gzipFilter")
@Scope(STATELESS)
@BypassInterceptors
@Filter(around = "org.jboss.seam.web.ajax4jsfFilterInstantiator")
public class GzipFilter extends net.sf.ehcache.constructs.web.filter.Filter
{

    private static final Logger LOG = Logger.getLogger(GzipFilter.class.getName());

    /**
     * Performs initialisation.
     *
     * @param filterConfig config
     */
    protected void doInit(FilterConfig filterConfig) throws Exception
    {
        //nothing required.
    }


    /**
     * A template method that performs any Filter specific destruction tasks.
     * Called from {@link #destroy()}
     */
    protected void doDestroy()
    {
        //noop
    }

    /**
     * Performs the filtering for a request.
     */
    protected void doFilter(final HttpServletRequest request, final HttpServletResponse response,
                            final FilterChain chain) throws Exception
    {
        if (!isDocStore(request) && !isIncluded(request) && acceptsEncoding(request, "gzip"))
        {
            // Client accepts zipped content
            if (LOG.isLoggable(Level.FINE))
            {
                LOG.fine(request.getRequestURL() + ". Writing with gzip compression");
            }

            // Create a gzip stream
            final ByteArrayOutputStream compressed = new ByteArrayOutputStream();
            final GZIPOutputStream gzout = new GZIPOutputStream(compressed);

            // Handle the request
            final GenericResponseWrapper wrapper = new GenericResponseWrapper(response, gzout);
            chain.doFilter(request, wrapper);
            wrapper.flush();

            gzout.close();

            //return on error or redirect code, because response is already committed
            int statusCode = wrapper.getStatus();
            if (statusCode != HttpServletResponse.SC_OK)
            {
                return;
            }

            //Saneness checks
            byte[] compressedBytes = compressed.toByteArray();
            boolean shouldGzippedBodyBeZero = ResponseUtil.shouldGzippedBodyBeZero(compressedBytes, request);
            boolean shouldBodyBeZero = ResponseUtil.shouldBodyBeZero(request, wrapper.getStatus());
            if (shouldGzippedBodyBeZero || shouldBodyBeZero)
            {
                compressedBytes = new byte[0];
            }

            // Write the zipped body
            //ResponseUtil.addGzipHeader(response);
            response.setHeader("Content-Encoding", "gzip");
            response.setContentLength(compressedBytes.length);


            response.getOutputStream().write(compressedBytes);
        } else
        {
            // Client does not accept zipped content - don't bother zipping
            if (LOG.isLoggable(Level.FINE))
            {
                LOG.fine(request.getRequestURL()
                        + ". Writing without gzip compression because the request does not accept gzip.");
            }
            chain.doFilter(request, response);
        }
    }


    /**
     * Checks if the request uri is an include.
     * These cannot be gzipped.
     *
     * @param request the request
     * @return true if included
     */
    private boolean isIncluded(final HttpServletRequest request)
    {
        final String uri = (String) request.getAttribute("javax.servlet.include.request_uri");
        final boolean includeRequest = !(uri == null);

        if (includeRequest && LOG.isLoggable(Level.FINE))
        {
            LOG.fine(request.getRequestURL() + " resulted in an include request. This is unusable, because" +
                    "the response will be assembled into the overrall response. Not gzipping.");
        }
        return includeRequest;
    }

    private boolean isDocStore(final HttpServletRequest request)
    {
        return request.getRequestURI().indexOf("/docstore/") > 0;
    }

    /**
     * Determine whether the user agent accepts GZIP encoding. This feature is part of HTTP1.1.
     * If a browser accepts GZIP encoding it will advertise this by including in its HTTP header:
     * <p/>
     * <code>
     * Accept-Encoding: gzip
     * </code>
     * <p/>
     * Requests which do not accept GZIP encoding fall into the following categories:
     * <ul>
     * <li>Old browsers, notably IE 5 on Macintosh.
     * <li>Internet Explorer through a proxy. By default HTTP1.1 is enabled but disabled when going
     * through a proxy. 90% of non gzip requests seen on the Internet are caused by this.
     * </ul>
     * As of September 2004, about 34% of Internet requests do not accept GZIP encoding.
     *
     * @param request the request
     * @return true, if the User Agent request accepts GZIP encoding
     */
    protected boolean acceptsGzipEncoding(HttpServletRequest request)
    {
        return acceptsEncoding(request, "gzip");
    }


}
0 голосов
/ 03 ноября 2009

Альтернативный фильтр сервлетов можно найти здесь:

http://onjava.com/pub/a/onjava/2003/11/19/filters.html

Как и Ehcache, он проверяет, поддерживает ли его браузер. Я не могу сказать категорически, хорошо ли это сочетается с Seam, но я использовал его в прошлом без проблем.

0 голосов
/ 23 сентября 2009

Я попробовал фильтр сервлетов, чтобы добавить сжатие GZIP (но не Ehcache), и не смог заставить его работать должным образом. В итоге я поставил Apache с mod_jk перед сервером приложений. Все, что мне потребовалось, - это несколько минут для настройки сжатия GIP, и я также чувствую себя намного более защищенным, поскольку вместо всего сервера приложений открыто только одно приложение.

...