いくつかのハッキングの後、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");
}
}