I come across some performence problems in my recent j2ee web project. It always takes a long time for the visitors to wait to see the whole web page. Most of the web content is text-based. So I decide to compress the web content using gzip, which can dramatically reduce download times for text-based files. This can be done in a Filter.
First, check whether a browser supports gzip compression. Browsers that support this feature will set the Accept-Encoding request header.
/** Does the client support gzip? */
public boolean isGzipSupported(HttpServletRequest request) {
String encodings = request.getHeader(”Accept-Encoding”);
return ((encodings != null) && (encodings.indexOf(”gzip”) != -1));
}
If a browser supports gzip, we can then send gzip-compressed content to it. The following is the whole code:
package com.esurfer.filters;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.zip.GZIPOutputStream;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class GzipFilter implements Filter {
private FilterConfig config;
public GzipFilter() {
}
public void init(FilterConfig filterConfig) throws ServletException {
this.config = filterConfig;
}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
// If the browser supports gzip, send compressed content.
// otherwise send the web content directly.
PrintWriter out;
if (isGzipSupported((HttpServletRequest) request)) {
out = getGzipWriter((HttpServletResponse) response);
((HttpServletResponse) response).setHeader(”Content-Encoding”,
”gzip”);
ResponseWrapper wrapper = new ResponseWrapper(
(HttpServletResponse) response);
chain.doFilter(request, wrapper);
out.print(wrapper.toString());
out.close();
} else {
chain.doFilter(request, response);
}
}
public void destroy() {
config = null;
}
/** Check the Accepting-Encoding header from the HTTP request. */
public boolean isGzipSupported(HttpServletRequest request) {
String encodings = request.getHeader(”Accept-Encoding”);
return ((encodings != null) && (encodings.indexOf(”gzip”) != -1));
}
/** Return gzipping PrintWriter for response. */
public PrintWriter getGzipWriter(HttpServletResponse response)
throws IOException {
return (new PrintWriter(
new GZIPOutputStream(response.getOutputStream())));
}
}
The java class used to wrap the response object:
package com.esurfer.filters;
import java.io.*;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
public class ResponseWrapper extends HttpServletResponseWrapper {
StringWriter writer = new StringWriter();
public ResponseWrapper(HttpServletResponse response) {
super(response);
}
public PrintWriter getWriter() {
return new PrintWriter(writer);
}
public String toString() {
return writer.toString();
}
}
To make it work, we need register the gzip filter in the deployment descriptor, and then map it to URL patterns.
<?xml version=”1.0″ encoding=”ISO-8859-1″?>
<!DOCTYPE web-app
PUBLIC “-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN”
“http://java.sun.com/dtd/web-app_2_3.dtd“>
<web-app>
<display-name>GzipFilter</display-name>
<description>
GzipFilter Test
</description>
<filter>
<filter-name>Compress</filter-name>
<filter-class>com.esurfer.filters.GzipFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>Compress</filter-name>
<url-pattern>*.html</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>Compress</filter-name>
<url-pattern>*.htm</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>Compress</filter-name>
<url-pattern>*.jsp</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>Compress</filter-name>
<url-pattern>*.css</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>Compress</filter-name>
<url-pattern>*.js</url-pattern>
</filter-mapping>
</web-app>
After finishing the steps above, we can examinate it using Web Page Analyzer provided by WebSiteOptimization.com. Which is a free website performance tool, and can be used to calculate page size, composition, and download time.
References
HTTP Compression http://www.port80software.com/products/httpzip/httpcompression
Compressing Web Content with mod_gzip and mod_deflate http://www.linuxjournal.com/article/6802
Servlet and JSP performance tuning http://www.javaworld.com/javaworld/jw-06-2004/jw-0628-performance.html
Java Platform Performance: Strategies and Tactics http://java.sun.com/docs/books/performance/
How can you speed up webpage loading using Java Servlets? — From HttpRevealer.com http://java.ittoolbox.com/pub/SC071902/httprevealer_servlets_itx.htm
Two Servlet Filters Every Web Application Should Have http://www.onjava.com/pub/a/onjava/2003/11/19/filters.html?page=1