博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Filter-全站GZIP压缩
阅读量:6912 次
发布时间:2019-06-27

本文共 5658 字,大约阅读时间需要 18 分钟。

hot3.png

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解压。

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压缩一般只处理文本内容,对图片、已经压缩过的文件则不进行压缩。这时就要在配置文件时,配置要过滤的资源。

  

 

 

三、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() {    }}

复制代码

 

  步骤:

    1、对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;    }}

复制代码

 

    2、改写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) ;    }}

复制代码

 

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

    4、然后获取Servlet 处理过后的数据,然后进行Gzip压缩。

    5、调用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

转载于:https://my.oschina.net/oschenxiaomo/blog/631860

你可能感兴趣的文章
利用TC进行流量控制(Qos) 原文:姜道友 著
查看>>
Samba简述
查看>>
人到中年,技术何以糊口
查看>>
错误代码:0x800704cf 不能访问网络位置(win7 访问不了局域网电脑) .
查看>>
Android版SDK与admob管理平台集成教程
查看>>
六、安装laravel5.1
查看>>
华为交换机批量加入 Vlan 方法
查看>>
async 与 await 线程调用顺序
查看>>
马的种类(十四)
查看>>
路由、交换如何Telnet远程配置。
查看>>
Linux文本查看命令之uniq
查看>>
三大闪存芯片的类型比较TLC/MLC/SLC(转载)
查看>>
面试题
查看>>
再见!史上最失败的windows系统!
查看>>
EditText 只能输入数字字母
查看>>
nginx的valid_referers指令——防盗链
查看>>
Spark DecisonTree DebugString Parser
查看>>
Laravel验证码
查看>>
tomcat 服务器 和 servlet 容器
查看>>
varchar(N)和char(N)中的N解析
查看>>