Каков наилучший метод для GZIP на страницах веб-приложений JSF-Seam
Я разрабатываю веб-приложение JSF на Tomcat, планирую использовать Seam в ближайшем будущем, и я хочу добавить сжатие наших веб-страниц и ресурсов (т.е. Javascript и файлы CSS). Я знаю три метода ответов GZIP в веб-среде Java:
-
Используйте фильтр Ehcache GZIP: он используется в Appfuse, поэтому он, вероятно, прочный и проверяет, поддерживает ли пользовательский агент GZIP перед его применением, но, похоже, у него проблемы с Seam, который мы будем использовать http://seamframework.org/Community/EHCacheGZipFilterIncompatibleWithSeam.
-
Используйте pjl-фильтр. Из вопроса stackoverflow: Компрессия Tomcat не добавляет кодировку содержимого: gzip в заголовке, похоже, что у нее нет утечек памяти, но я не знать, есть ли у него проблемы с швом или нет.
-
Используйте Tomcat, встроенный в сжатие, хотя он может не предоставлять кодировку содержимого (Tomcat 6.0.14, похоже, работает нормально, но вы можете предоставить только черный список, для которого нельзя применять сжатие пользовательских агентов.
Есть ли у кого-нибудь опыт работы с этими методами в среде JSF-Seam? Какое "лучшее" решение?
Спасибо,
Glen
Ответы
Ответ 1
Фильтр GZIP значительно сократит время начальной загрузки.
Вы можете дополнительно реализовать cacheFilter, чтобы обеспечить производительность ваших экранов наравне с пользовательским интерфейсом на основе JavaScript (fooobar.com/questions/8784/...).
Для клиентских компонентов вы можете использовать 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
Ответ 2
Как добавить добавочный интерфейс nginx
и позволить ему выполнить сжатие (и кеширование)?
http://wiki.nginx.org/Main
В этом случае принадлежит serverfalut:)
Ответ 3
Вам следует попробовать API Jawr
Ответ 4
Мы используем JBoss Seam
в JBoss AS
прокси и балансировку нагрузки <<22 > + mod_proxy_ajp
с помощью mod_deflate
для сжатия исходящего трафика.
Преимущества этой настройки
- множество примеров в сети
- простая настройка/отладка с учетом особенностей различных пользовательских агентов
- изменение конфигурации во время выполнения (
apachectl graceful
вместо перезапуска webapp/tomcat для отражения изменений).
Ответ 5
Используйте 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-коннектору.
Ответ 6
Я попробовал фильтр Servlet, чтобы добавить сжатие GZIP (но не Ehcache) и не смог заставить его работать правильно. В итоге я поставил Apache с mod_jk перед сервером приложений. Все, что потребовалось, было несколько минут, чтобы настроить GIP compressiion, и я также чувствую себя намного более безопасным, поскольку только одно приложение открыто, а не весь сервер приложений.
Ответ 7
Альтернативный сервлет-фильтр можно найти здесь:
http://onjava.com/pub/a/onjava/2003/11/19/filters.html
Как и Ehcache, он проверяет, поддерживает ли браузер его. Я не могу сказать категорически, если он хорошо играет с Seam, но я использовал его в прошлом без проблем.
Ответ 8
Я доволен фильтром 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");
}
}