Gzip Servlet Filter in Spring MVC
Posted By : Summy Saurav | 20-May-2014
In this blog I will explain how to use GZip servlet filter in Spring web application to speeds up the page load.
GZip servlet filter is used to compress JSP data (html,JS,CSS) and sent to browser , then browser will automatically decompresses it . This speeds up the page load compare to not compressed data sent to browser.
How it works:
Before rendering the jsp page, filter will be fetching browser properties via a header named as ACCEPT_ENCODING. So if the browser support the GZip encoding format , filter will wrap the servletResponse in our custom wrapper and send the wrapped response to browser and then browser will decompress it. If browser does not support Gzip encoding format then our filter will send the non wrapped response.
whenever a request is send to server GZip servlet filter wraps the HttpServletResponse and override the getWritter() and getOutputStream() method of ServletResponse to write the compressed string on response.
Here is the Code
GZIPFilter.java
public class GZIPFilter implements Filter
{
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)
{
System.out.println("Processing GZIPFilter");
//searching for 'gzip' in ACCEPT_ENCODING header
if (acceptEncoding.indexOf("gzip") >= 0)
{
GZIPResponseWrapper gzipResponse = new GZIPResponseWrapper(httpResponse);
chain.doFilter(request, gzipResponse);
gzipResponse.finish();
return;
}
}
chain.doFilter(request, response);
}
}
Now here is the code for ServletResponseWrapper which override the methods of ServletResponse to write the compressed response.
GZIPResponseWrapper.java
public class GZIPResponseWrapper extends HttpServletResponseWrapper
{
private GZIPResponseStream gzipStream;
private ServletOutputStream outputStream;
private PrintWriter printWriter;
public GZIPResponseWrapper(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()));
}
System.out.println("GZIPFilter is Working fine!!!!!");
return printWriter;
}
/* Creates a new output stream for writing compressed data in
* the GZIP file format. */
private void initGzip() throws IOException
{
gzipStream = new GZIPResponseStream(getResponse().getOutputStream());
}
}
GZIPResponseStream.java
public class GZIPResponseStream extends ServletOutputStream
{
GZIPOutputStream gzipStream;
final AtomicBoolean open = new AtomicBoolean(true);
OutputStream output;
public GZIPResponseStream(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);
}
}
Thanks
Summy Saurav
Request for Proposal
Cookies are important to the proper functioning of a site. To improve your experience, we use cookies to remember log-in details and provide secure log-in, collect statistics to optimize site functionality, and deliver content tailored to your interests. Click Agree and Proceed to accept cookies and go directly to the site or click on View Cookie Settings to see detailed descriptions of the types of cookies and choose whether to accept certain cookies while on the site.
About Author
Summy Saurav
Summy is a kind of conscientious type of personality always be stable and practical in making decision; quick learner and problem solving attitude within a team . He is Fond of drawing,reading and computer programming