GZIP --压缩

// 第1步、使用File类找到一个文件
  File f= new File("d:" + File.separator + "test.txt") ; // 声明File对象
  // 第2步、通过子类实例化父类对象
  OutputStream out = null ; // 准备好一个输出的对象
  out = new FileOutputStream(f)  ; // 通过对象多态性,进行实例化
  // 第3步、进行写操作
  String str = "Hello World!!!" ;  // 准备一个字符串
  byte b[] = str.getBytes() ;   // 只能输出byte数组,所

以将字符串变为byte数组
  out.write(b) ;      // 将内容输出,

保存文件
  // 第4步、关闭输出流
  out.close() ;  

写上面这段代码的意义是为了理解write到缓冲区和文件的的区别,区别不大,都是一样的写


public static void writeHtmlGzip(HttpServletResponse response,String obj,boolean isCache) {
Assert.notNull(response, "response must not be null");
response.setContentType("text/html;charset=utf-8");

if(isCache){
setResponseCache(response);
}
        try{
    OutputStream out = response.getOutputStream();
    //为了将缓冲期的流转化成字节数组,ByteArrayOutputStream 可以toByteArray() 出byte数组
            ByteArrayOutputStream compressed = new ByteArrayOutputStream();

            // 创建 GZIPOutputStream 输出流时,需要传一个带有缓冲区的输出流,所以我们ByteArrayOutputStream 输出流。而且,                   //ByteArrayOutputStream还可以获取byte[];
            GZIPOutputStream gzout = new GZIPOutputStream(compressed);

            //写入缓冲期进行压缩,
            gzout.write(obj.getBytes("utf-8"));
            gzout.flush();
            
            gzout.close();
            //转化成字节数组
            byte[] data =compressed.toByteArray();
            //指定Vary: Accept-Encoding标头可告诉代理服务器缓存两种版本的资源:压缩和非压缩
            response.addHeader("Vary", "Accept-Encoding");
            //告诉浏览器,输出信息用gzip进行压缩了
            response.setHeader("Content-Encoding", "gzip");
            //压缩长度
            response.setContentLength(data.length);
            //输出
            out.write(data);
            out.flush();
            out.close();
            
        }catch(Exception e){
        throw new RuntimeException(e);
        }
}




Filter之——GZIP全站压缩

  GZIP 与zip区别主要是适应系统不同,还有就是压缩率不一样;
普遍使用的是zip压缩,Windows系统下就用zip
gzip为高压,可以把文件压缩得更小,便于放网盘或者网上供人下载;gzip是Linux下面用的格式,一般在Linux下解压,如果用Windows下的程序解压有可能丢失其中某些文件或属性。

 


一、进行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 返回的数据。更细一点的流程如下图:

    

    

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值