Filter之——GZIP全站壓縮


     GZIP壓縮:將壓縮后的文本文件,發送給瀏覽器,減少流量。

 

一、進行gzip壓縮條件:

  1、請求頭:Accept-Encoding : gzip  告訴服務器,該瀏覽器支持gzip壓縮。

  2、響應頭:Content-Encoding : gzip.  告訴瀏覽器,輸出信息用gzip進行壓縮了。

  3、兩個主要類:

    ByteArrayOutputStream : 內存輸出流,還有緩存。

    GZIPOutputStream 包裝流;

 

二、gzip 壓縮步驟:

    1、獲取字符的字節數組 byte[] buf = str.getBytes() ;

    2、通過GZIPOutputStream 包裝流進行輸入:

       創建 GZIPOutputStream 輸出流時,需要傳一個帶有緩沖區的輸出流,所以我們ByteArrayOutputStream 輸出流。而且,ByteArrayOutputStream還可以獲取byte[];

    3、將ByteArrayOutputStream 流中的緩存數據,轉換成字節數組。

    4、將 壓縮后的字節數組通過response 進行輸出。不過輸出之前要設置Content-Encoding 響應頭,value為gzip。告訴瀏覽器數據進行了gzip壓縮,要使用gzip解壓

 1             String str = "我是個測試";
 2             //1\獲取字節數組
 3             byte[] bytes = str.getBytes() ;
 4             
 5             System.out.println("壓縮前的長度:" + bytes.length); 
 6             //2\
 7             ByteArrayOutputStream baos = new ByteArrayOutputStream() ; 
 8             GZIPOutputStream  gzip = new GZIPOutputStream(baos) ;
 9             
10             gzip.write(bytes) ; 
11             gzip.close() ;
12             //3\
13             bytes = baos.toByteArray() ;
14             System.out.println("壓縮后的長度:" + bytes.length);

    數據較小是,壓縮的效果不是很明顯,不過數據越大,壓縮效果越明顯。所以,GZIP壓縮一般只處理文本內容,對圖片、已經壓縮過的文件則不進行壓縮。這時就要在配置文件時,配置要過濾的資源

  

 

 

三、GZIPFilter

 1 import itheima.decorator.MyHttpServletResponse;
 2 
 3 import java.io.ByteArrayOutputStream;
 4 import java.io.IOException;
 5 import java.util.zip.GZIPOutputStream;
 6 
 7 import javax.servlet.Filter;
 8 import javax.servlet.FilterChain;
 9 import javax.servlet.FilterConfig;
10 import javax.servlet.ServletException;
11 import javax.servlet.ServletRequest;
12 import javax.servlet.ServletResponse;
13 import javax.servlet.http.HttpServletRequest;
14 import javax.servlet.http.HttpServletResponse;
15 /**
16  * Gzip壓縮過濾器
17  * @author 賀佐安
18  *
19  */
20 public class GZIPFilter implements Filter{
21 
22     public void init(FilterConfig filterConfig) throws ServletException {
23     }
24 
25     public void doFilter(ServletRequest req , ServletResponse resp ,
26             FilterChain chain) throws IOException, ServletException {
27         HttpServletResponse response = (HttpServletResponse) resp ; 
28         HttpServletRequest request = (HttpServletRequest) req ;
29         //創建HttpServletResponse 包裝類的實例
30         MyHttpServletResponse myResponse = new MyHttpServletResponse(response) ;
31         
32         chain.doFilter(request, myResponse) ;
33         
34         //GZIP壓縮:
35         byte[] buff = myResponse.getBufferedBytes() ;  
36         //創建緩存容器:
37         ByteArrayOutputStream baos = new ByteArrayOutputStream() ;
38         
39         GZIPOutputStream gzip = new GZIPOutputStream(baos) ;
40         
41         gzip.write(buff) ;
42         
43         gzip.close() ;
44         
45         buff = baos.toByteArray() ;
46          
47         //設置響應頭;
48         response.setHeader("Content-Encoding", "gzip");
49         response.setContentLength(buff.length) ;  
50         response.getOutputStream().write( buff) ;
51     }
52 
53     public void destroy() {
54     }
55 
56 }

 

  步驟:

    1、對HttpServletResponse 進行包裝 :改寫getOutputStream()、getWriter() 方法,並且設置一個臨時容器,存儲Serlvet處理后要輸出的數據。 這里是重點。

 1 import java.io.ByteArrayOutputStream;
 2 import java.io.IOException;
 3 import java.io.OutputStreamWriter;
 4 import java.io.PrintWriter;
 5 
 6 import javax.servlet.ServletOutputStream;
 7 import javax.servlet.http.HttpServletResponse;
 8 import javax.servlet.http.HttpServletResponseWrapper;
 9 /**
10  * 對HttpServletResponse 進行包裝
11  * @author 賀佐安
12  *
13  */
14 public class MyHttpServletResponse extends HttpServletResponseWrapper {
15     //定義一個容器,用來存儲Serlvet 處理完后response 寫出的數據
16     private ByteArrayOutputStream bos = new ByteArrayOutputStream()  ;
17     private PrintWriter printWriter = null;
18     public MyHttpServletResponse(HttpServletResponse  response) {
19         super(response) ;
20     }
21     //處理字節流輸出的情況
22     public ServletOutputStream getOutputStream() throws IOException {
23         return new MyServletOutputStream(bos); 
24     } 
25 
26     //處理字符流輸出的情況:用字符流時要注意亂碼:字節轉字符要查碼表,字符轉字節也要查碼表
27     public PrintWriter getWriter() throws IOException {
28         printWriter  = new PrintWriter(new OutputStreamWriter(bos, super.getCharacterEncoding())) ;
29         return printWriter;
30     }
31     //獲取response 寫出的數據
32     public byte[] getBufferedBytes(){
33         try {
34             if (printWriter != null) 
35                 printWriter.close() ;
36             bos.flush() ;
37         } catch (IOException e) {
38             e.printStackTrace(); 
39         }
40         byte[] byteArray = bos.toByteArray() ;
41         return  byteArray;
42     }
43 }

 

    2、改寫getOutputStream 方法時,要返回一個SerlvetOutputStream 類實例,因為SerlvetOutputStream是抽象類,不能創建實例,所以要重寫SerlvetOutputStream 類:

 1 import java.io.ByteArrayOutputStream;
 2 import java.io.IOException;
 3 
 4 import javax.servlet.ServletOutputStream;
 5 /**
 6  * 包裝ServletOutputStream ,改寫write 方法。
 7  * @author 賀佐安
 8  *
 9  */
10 public class MyServletOutputStream extends ServletOutputStream {
11     private ByteArrayOutputStream bos = null ; 
12     public MyServletOutputStream (ByteArrayOutputStream bos) {
13         this.bos = bos ;
14     }
15     public void write(int b) throws IOException {
16         bos.write(b) ;
17     }
18 }

 

    3、將包裝過的HttpServletResponse 類的實例放行。

    4、然后獲取Servlet 處理過后的數據,然后進行Gzip壓縮。

    5、調用ServletResponse 的實例,將壓縮后的數據寫出去。

 1     //GZIP壓縮:
 2         byte[] buff = myResponse.getBufferedBytes() ;  
 3         //創建緩存容器:
 4         ByteArrayOutputStream baos = new ByteArrayOutputStream() ;
 5         
 6         GZIPOutputStream gzip = new GZIPOutputStream(baos) ;
 7         
 8         gzip.write(buff) ;
 9         
10         gzip.close() ;
11         
12         buff = baos.toByteArray() ;
13          
14         //設置響應頭;
15         response.setHeader("Content-Encoding", "gzip");
16         response.setContentLength(buff.length) ;  
17         response.getOutputStream().write( buff) ;

  

  以上便是用Filter 對一些文本資源進行GIZP壓縮的步驟。重點就是第二步,如何獲取Servlet 返回的數據。更細一點的流程如下圖:

    

    

 

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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM