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(); } }