Java中使用filter机制回GZIP压缩网页

Java中使用filter机制来GZIP压缩网页

参考:http://blog.csdn.net/a_heng/article/details/4579979

http://snowolf.iteye.com/blog/643443

 

import java.io.IOException;
import java.util.zip.GZIPOutputStream;

import javax.servlet.ServletOutputStream;
import javax.servlet.WriteListener;

/**
 * 使用GZIPOutputStream重新创建ServletOutputStream类的write()。
 * 
 * @author Zhongqing.Lin
 * @since 2014年10月12日 上午8:37:55
 */

public class GZipServletOutputStream extends ServletOutputStream
{
	private GZIPOutputStream gzipOutputStream;

	@Override
	public boolean isReady()
	{
		return false;
	}

	public GZipServletOutputStream(ServletOutputStream servletOutputStream) throws IOException
	{
		super();
		this.gzipOutputStream = new GZIPOutputStream(servletOutputStream);
	}

	public GZIPOutputStream getGzipOutputStream()
	{
		return gzipOutputStream;
	}

	public void finish() throws IOException
	{
		gzipOutputStream.finish();
	}

	@Override
	public void setWriteListener(WriteListener listener)
	{
	}

	@Override
	public void write(int b) throws IOException
	{
		gzipOutputStream.write(b);
	}

	@Override
	public void write(byte[] b) throws IOException
	{
		gzipOutputStream.write(b);
	}

	@Override
	public void write(byte[] b, int off, int len) throws IOException
	{
		gzipOutputStream.write(b, off, len);
	}

	@Override
	public void flush() throws IOException
	{
		gzipOutputStream.flush();
	}

	@Override
	public void close() throws IOException
	{
		gzipOutputStream.close();
	}

}

 

import java.io.IOException;

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.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebFilter(filterName = "GZipServletResponseFilter", urlPatterns = {"/*"})
public class GZipServletResponseFilter implements Filter
{

	@Override
	public void init(FilterConfig filterConfig) throws ServletException
	{
	}

	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException
	{
		HttpServletRequest req = (HttpServletRequest) request;
		HttpServletResponse resp = (HttpServletResponse) response;
		String encoding = req.getHeader("Accept-Encoding");
		//检查是否接受GZIP压缩
		if ((encoding != null) && (encoding.indexOf("gzip") > -1))
		{
			//创建响应封装器
			GzipServletResponseWrapper respWrapper = new GzipServletResponseWrapper(resp);
			//设置响应内容编码为gzip格式。Content-Encoding单词首字母必须大写
			respWrapper.setHeader("Content-Encoding", "gzip");
			
			//调用下一个过滤器
			chain.doFilter(req, respWrapper);
			respWrapper.flush();
		}
		else
		{
			//若是请求头不接受压缩,直接调用下一个过滤器
			chain.doFilter(req, resp);
		}
	}

	@Override
	public void destroy()
	{
	}

}

 

/**
 * 用GZipOutputStream包装
 * 
 * @author Zhongqing.Lin
 * @since 2014年10月12日 上午8:38:48
 */
public class GzipServletResponseWrapper extends HttpServletResponseWrapper
{

	private GZipServletOutputStream gzServletOutputStream;
	private PrintWriter printWriter;

	public GzipServletResponseWrapper(HttpServletResponse response)
	{
		super(response);
	}

	@Override
	public ServletOutputStream getOutputStream() throws IOException
	{
		//遵循Servlet规范书中规定,在同一个请求期间,getWriter()和getOutputStream()只能择一调用;
		//若是已调用过getWriter(),再次调用getOutputStream()就抛出异常
		if (printWriter != null)
		{
			throw new IllegalStateException();
		}
		if (gzServletOutputStream == null)
		{
			gzServletOutputStream = new GZipServletOutputStream(getResponse().getOutputStream());
		}
		return gzServletOutputStream;
	}

	@Override
	public PrintWriter getWriter() throws IOException
	{
		if (gzServletOutputStream != null)
		{
			throw new IllegalStateException();
		}
		if (printWriter == null)
		{
			gzServletOutputStream = new GZipServletOutputStream(getResponse().getOutputStream());
			OutputStreamWriter osw = new OutputStreamWriter(gzServletOutputStream, getResponse().getCharacterEncoding());
			printWriter = new PrintWriter(osw);
		}
		return printWriter;
	}

	public GZIPOutputStream getGZipOutputStream()
	{
		if (this.gzServletOutputStream == null)
		{
			return null;
		}
		return this.gzServletOutputStream.getGzipOutputStream();
	}
	
	public void flush() throws IOException
	{
		//如果printWriter被使用到,那么需要先将调用printWriter的flush()方法
		if (printWriter != null)
		{
			printWriter.flush();
		}
		//在输出流关闭前将压缩数据输写到输出流
		gzServletOutputStream.finish();
	}

}