Googling: request.getHeader("Accept-Encoding"); gzip compression
Compressing web content with GZip and Filter
ref.> http://www.jroller.com/coreteam/entry/compressing_web_content_with_gzip
Compressing web content with GZip and Filter
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
Posted at 04:01PM Sep 07, 2005 by Li Haijun in Java | Comments[8]
'◆ 무한한 가능성 > & JAVA' 카테고리의 다른 글
JAVA for Eclipse - Environment Variables (0) | 2014.09.29 |
---|---|
[Eclipse] java jdk 환경변수 등록 (0) | 2014.07.28 |
[Session] Session Timer 세션 타이머 세션 시간 (0) | 2014.02.17 |
2012년 분야별 최고의 오픈소스 소프트웨어 124선 (0) | 2013.07.12 |
Java 프로그래머 책들 (0) | 2013.07.11 |
The code you get from https://atleap.dev.java.net/source/browse/atleap/application/src/web/com/blandware/atleap/webapp/servlet/DefaultServlet.java
Andrey Grebnev
http://www.jroller.com/page/agrebnev
Posted by Andrey Grebnev on September 07, 2005 at 08:37 PM CST #
1. Multipart MIME requests (i.e. file uploads) won't work in some situations. Sorry, but I am not sure what browser has this problem. I've heard of other people having this same problem.
2. If you try to print a page with Netscape while using SSL + gzip you'll get garbage. This might be an older Netscape bug fixed in more recent versions.
I suggest you use gzip on selected pages that contain a large amount of content.
Posted by Michael Slattery on September 07, 2005 at 09:49 PM CST #
Posted by esurfer on September 07, 2005 at 10:26 PM CST #
>chain.doFilter(request, wrapper);
>out.print(wrapper.toString());
I suppose you do not use streaming here...
What about mine:
**********
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Enumeration;
public class GZIPFilter implements Filter
{
public void init(FilterConfig filterConfig){}
public void destroy() {}
public void doFilter (ServletRequest req, ServletResponse res,
FilterChain chain) throws IOException, ServletException
{
if (req instanceof HttpServletRequest &&
res instanceof HttpServletResponse)
{
HttpServletRequest request = (HttpServletRequest)req;
Enumeration e = request.getHeaders("Accept-Encoding");
while (e.hasMoreElements())
{
String name = (String)e.nextElement();
if (name != null && name.indexOf("gzip") != -1)
{ // compress;
HttpServletResponse response = (HttpServletResponse)res;
GZIPResponseWrapper wr = new GZIPResponseWrapper(response);
try
{
chain.doFilter(request, wr);
}
finally
{
wr.closeBuffer();
}
return;
}
}
}
chain.doFilter(req, res);
}
}
**********
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
import javax.servlet.ServletOutputStream;
import java.io.PrintWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
public class GZIPResponseWrapper extends HttpServletResponseWrapper
{
private GZIPServletOutputStream stream;
private HttpServletResponse res;
private PrintWriter writer;
public GZIPResponseWrapper(HttpServletResponse res)
{
super(res);
this.res = res;
}
public ServletOutputStream getOutputStream() throws IOException
{
if (writer != null)
throw new IllegalStateException("getWriter() has already been called for this response");
if (stream == null)
{
res.addHeader("Content-Encoding", "gzip");
stream = new GZIPServletOutputStream(res.getOutputStream());
}
return stream;
}
public PrintWriter getWriter() throws IOException
{
if (stream != null)
throw new IllegalStateException("getOutputStream() has already been called for this response");
if (writer == null)
{
String enc = getCharacterEncoding();
writer = new PrintWriter(new OutputStreamWriter(getOutputStream(), enc));
}
return writer;
}
public void flushBuffer() throws IOException
{
if (writer != null)
writer.flush();
else if (stream != null)
stream.flush();
}
public void closeBuffer() throws IOException
{
if (writer != null)
writer.close();
else if (stream != null)
stream.close();
}
}
***********
import javax.servlet.ServletOutputStream;
import java.io.IOException;
import java.io.BufferedOutputStream;
import java.util.zip.GZIPOutputStream;
public class GZIPServletOutputStream extends ServletOutputStream
{
private GZIPOutputStream gzip;
public GZIPServletOutputStream(ServletOutputStream out) throws IOException
{
gzip = new GZIPOutputStream(new BufferedOutputStream(out));
}
public void write(int b) throws IOException
{
gzip.write(b);
}
public void write(byte b[]) throws IOException
{
gzip.write(b, 0, b.length);
}
public void write(byte b[], int off, int len) throws IOException
{
gzip.write(b, off, len);
}
public void close() throws IOException
{
gzip.flush();
gzip.close();
}
public void flush() throws IOException
{
gzip.flush();
}
}
Cheers,
Dim
Posted by Dim on September 07, 2005 at 10:38 PM CST #
Posted by esurfer on September 07, 2005 at 11:19 PM CST #
Posted by Lutz Hühnken on September 14, 2005 at 06:13 PM CST #
For small projects I just can't force people to install apache over their windowz (sometimes they complain even of java...). Company that uses linux usually has apache installed so in this situation it's easy with mod_gzip
Posted by Dim on September 14, 2005 at 11:28 PM CST #
Posted by 68.33.107.135 on July 03, 2013 at 10:15 AM CST #