Filter-全站GZIP压缩

GZIP压缩:将压缩后的文本文件,发送给浏览器,减小流量。java

 

1、进行gzip压缩条件:数组

  一、请求头:Accept-Encoding : gzip  告诉服务器,该浏览器支持gzip压缩。浏览器

  二、响应头:Content-Encoding : gzip.  告诉浏览器,输出信息用gzip进行压缩了。缓存

  三、两个主要类:服务器

    ByteArrayOutputStream : 内存输出流,还有缓存。app

    GZIPOutputStream 包装流;测试

 

2、gzip 压缩步骤:this

    一、获取字符的字节数组 byte[] buf = str.getBytes() ;spa

    二、经过GZIPOutputStream 包装流进行输入:code

       建立 GZIPOutputStream 输出流时,须要传一个带有缓冲区的输出流,因此咱们ByteArrayOutputStream 输出流。并且,ByteArrayOutputStream还能够获取byte[];

    三、将ByteArrayOutputStream 流中的缓存数据,转换成字节数组。

    四、将 压缩后的字节数组经过response 进行输出。不过输出以前要设置Content-Encoding 响应头,value为gzip。告诉浏览器数据进行了gzip压缩,要使用gzip解压

String str = "我是个测试";
            //1\获取字节数组
            byte[] bytes = str.getBytes() ;
            
            System.out.println("压缩前的长度:" + bytes.length); 
            //2\
            ByteArrayOutputStream baos = new ByteArrayOutputStream() ; 
            GZIPOutputStream  gzip = new GZIPOutputStream(baos) ;
            
            gzip.write(bytes) ; 
            gzip.close() ;
            //3\
            bytes = baos.toByteArray() ;
            System.out.println("压缩后的长度:" + bytes.length);


    数据较小是,压缩的效果不是很明显,不过数据越大,压缩效果越明显。因此,GZIP压缩通常只处理文本内容,对图片、已经压缩过的文件则不进行压缩。这时就要在配置文件时,配置要过滤的资源

  

 

 

3、GZIPFilter

复制代码

 import itheima.decorator.MyHttpServletResponse;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
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;
/**
 * Gzip压缩过滤器
 * @author 贺佐安
 *
 */
public class GZIPFilter implements Filter{

    public void init(FilterConfig filterConfig) throws ServletException {
    }

    public void doFilter(ServletRequest req , ServletResponse resp ,
            FilterChain chain) throws IOException, ServletException {
        HttpServletResponse response = (HttpServletResponse) resp ; 
        HttpServletRequest request = (HttpServletRequest) req ;
        //建立HttpServletResponse 包装类的实例
        MyHttpServletResponse myResponse = new MyHttpServletResponse(response) ;
        
        chain.doFilter(request, myResponse) ;
        
        //GZIP压缩:
        byte[] buff = myResponse.getBufferedBytes() ;  
        //建立缓存容器:
        ByteArrayOutputStream baos = new ByteArrayOutputStream() ;
        
        GZIPOutputStream gzip = new GZIPOutputStream(baos) ;
        
        gzip.write(buff) ;
        
        gzip.close() ;
        
        buff = baos.toByteArray() ;
         
        //设置响应头;
        response.setHeader("Content-Encoding", "gzip");
        response.setContentLength(buff.length) ;  
        response.getOutputStream().write( buff) ;
    }

    public void destroy() {
    }

}

复制代码

 

  步骤:

    一、对HttpServletResponse 进行包装 :改写getOutputStream()、getWriter() 方法,而且设置一个临时容器,存储Serlvet处理后要输出的数据。 这里是重点。

复制代码

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
/**
 * 对HttpServletResponse 进行包装
 * @author 贺佐安
 *
 */
public class MyHttpServletResponse extends HttpServletResponseWrapper {
    //定义一个容器,用来存储Serlvet 处理完后response 写出的数据
    private ByteArrayOutputStream bos = new ByteArrayOutputStream()  ;
    private PrintWriter printWriter = null;
    public MyHttpServletResponse(HttpServletResponse  response) {
        super(response) ;
    }
    //处理字节流输出的状况
    public ServletOutputStream getOutputStream() throws IOException {
        return new MyServletOutputStream(bos); 
    } 

    //处理字符流输出的状况:用字符流时要注意乱码:字节转字符要查码表,字符转字节也要查码表
    public PrintWriter getWriter() throws IOException {
        printWriter  = new PrintWriter(new OutputStreamWriter(bos, super.getCharacterEncoding())) ;
        return printWriter;
    }
    //获取response 写出的数据
    public byte[] getBufferedBytes(){
        try {
            if (printWriter != null) 
                printWriter.close() ;
            bos.flush() ;
        } catch (IOException e) {
            e.printStackTrace(); 
        }
        byte[] byteArray = bos.toByteArray() ;
        return  byteArray;
    }
}

复制代码

 

    二、改写getOutputStream 方法时,要返回一个SerlvetOutputStream 类实例,由于SerlvetOutputStream是抽象类,不能建立实例,因此要重写SerlvetOutputStream 类:

复制代码

 import java.io.ByteArrayOutputStream;
import java.io.IOException;

import javax.servlet.ServletOutputStream;
/**
 * 包装ServletOutputStream ,改写write 方法。
 * @author 贺佐安
 *
 */
public class MyServletOutputStream extends ServletOutputStream {
    private ByteArrayOutputStream bos = null ; 
    public MyServletOutputStream (ByteArrayOutputStream bos) {
        this.bos = bos ;
    }
    public void write(int b) throws IOException {
        bos.write(b) ;
    }
}

复制代码

 

    三、将包装过的HttpServletResponse 类的实例放行。

    四、而后获取Servlet 处理事后的数据,而后进行Gzip压缩。

    五、调用ServletResponse 的实例,将压缩后的数据写出去。

复制代码

 //GZIP压缩:
        byte[] buff = myResponse.getBufferedBytes() ;  
        //建立缓存容器:
        ByteArrayOutputStream baos = new ByteArrayOutputStream() ;
        
        GZIPOutputStream gzip = new GZIPOutputStream(baos) ;
        
        gzip.write(buff) ;
        
        gzip.close() ;
        
        buff = baos.toByteArray() ;
         
        //设置响应头;
        response.setHeader("Content-Encoding", "gzip");
        response.setContentLength(buff.length) ;  
        response.getOutputStream().write( buff) ;

复制代码

  

  以上即是用Filter 对一些文本资源进行GIZP压缩的步骤。重点就是第二步,如何获取Servlet 返回的数据。更细一点的流程以下图:

    

    

 

 --------------------------------------------------------------------------------------------更新:2013年7月21日 22:34:54

相关文章
相关标签/搜索