压缩过滤器—全站压缩

作者: 小小蒜头 | 来源:发表于2017-11-03 09:59 被阅读16次

前面我介绍的都是Request增强的案例,下面将介绍Response对象的增强。

Servlet API中提供了Response对象的Decorator设计模式实现类HttpServletResponseWrapper,(HttpServletResponseWrapper类实现了Response接口中的所有方法,但这些方法的内部实现都是仅仅调用了一下所包装的Response对象对应的方法)以避免用户在对Response对象进行增强时需要实现response接口中的所有方法。

案例:利用过滤器实现全站压缩

思路:

通过Filter向目标页面传递一个自定义的response对象。

  • 在自定义的response对象中,重写getOutputStream方法和getWriter方法,使目标资源调用此方法输出页面内容时,获得的是我们自定义的ServletOutputStream对象。
  • 在我们自定义的ServletOutputStream对象中,重写write方法,使写出的数据到一个buffer中。

当页面输出完成后,在Filter中就可得到页面写出的数据,从而我们可以调用GzipOutputStream对数据进行压缩后再写出给浏览器,以此完成响应正文件压缩功能。

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

进行gzip压缩条件:

  1. 请求头:Accept-Encoding :gzip 告诉服务器,该浏览器支持gzip压缩。
  2. 响应头:Content-Encoding: gzip. 告诉浏览器,输出信息用gzip进行压缩了。
  3. 两个主要类:ByteArrayOutputStream: 内存输出流,还有缓存。GZIPOutputStream 包装流;
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;


        //采用增强类传过去
        MyResponse myResponse = new MyResponse(response);
        filterChain.doFilter(request, myResponse);

用增强版的response放行到servlet中去用(让后台把数据 写到 bout中 ),分别写字节流函数的getOutputStream() 和字符流的getWriter()

class MyResponse extends HttpServletResponseWrapper {

        private ByteArrayOutputStream bout = new ByteArrayOutputStream();//往这个流里写数据
        private HttpServletResponse response;
        private PrintWriter pw;

        public MyResponse(HttpServletResponse response) {
            super(response);
            this.response = response;
        }

        @Override
        public ServletOutputStream getOutputStream() throws IOException {

            return new MyServletOutputStream(bout);//response.getOutputStream().write("hahah");
        }

        @Override
        public PrintWriter getWriter() throws IOException {
            pw = new PrintWriter(new OutputStreamWriter(bout, response.getCharacterEncoding()));
            return pw;//MyResponse.getWriter("as");
        }

        //数据已经写到bout里,现在需要得到这些数据
        public byte[] getBuffer() {

            if (pw != null) {
                pw.close();
            }
            return bout.toByteArray();
        }
    }

改写getOutputStream 方法时,要返回一个SerlvetOutputStream 类实例,因为SerlvetOutputStream是抽象类,不能创建实例,所以要重写SerlvetOutputStream 类。

class MyServletOutputStream extends ServletOutputStream {
        private ByteArrayOutputStream bout;

        //构造函数接收MyResponse里的bout
        public MyServletOutputStream(ByteArrayOutputStream bout) {
            this.bout = bout;
        }

        @Override
        public boolean isReady() {
            return false;
        }

        @Override
        public void setWriteListener(WriteListener writeListener) {

        }

        //当调用write方法写数据时,控制数据进bout里
        @Override
        public void write(int b) throws IOException {
            bout.write(b);
        }
    }

然后获取Servlet 处理过后的数据,然后进行Gzip压缩。再调用ServletResponse 的实例,将压缩后的数据写出去。

 //取出缓冲的数据压缩后输出
        byte out[] = myResponse.getBuffer();//得到目标资源的输出

        System.out.println("压缩之前:" + out.length);
        byte gzipout[] = gzip(out);
        System.out.println("压缩之后:" + gzipout.length);
        response.setHeader("content-encoding", "gzip");
        response.setHeader("content-length", gzipout.length + "");

        response.getOutputStream().write(gzipout);

在servlet中进行数据测试:

        String data = "qsadf微博等级开车门,曹禺搜索";
        // response.getOutputStream().write(data.getBytes("UTF-8"));
        response.getWriter().write(data);

web.xml

    <filter>
        <filter-name>GzipFilter</filter-name>
        <filter-class>cn.itcast.filter.GzipFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>GzipFilter</filter-name>
        <url-pattern>/*</url-pattern>
        <dispatcher>FORWARD</dispatcher>
        <dispatcher>REQUEST</dispatcher>
    </filter-mapping>

源代码:https://github.com/yvettee36/GZIPFilter
上篇:敏感词过滤器

相关文章

  • 压缩过滤器—全站压缩

    前面我介绍的都是Request增强的案例,下面将介绍Response对象的增强。 Servlet API中提供了R...

  • TCD

    部门三厂 岗位 过滤器清洗 提案人 朱均 描述 现在过滤器清洗是用压缩空气直接吹装,在压缩空气吹的时候对现场...

  • H264压缩技术

    帧内压缩技术 有损压缩 帧间压缩 有损压缩

  • 图片压缩

    Android图片压缩常用的有质量压缩、尺寸压缩、采样率压缩以及通过JNI调用libjpeg库来进行压缩(尺寸压缩...

  • shell命令整理(七)

    打包压缩 window打包压缩工具: linux打包压缩工具: 打包 解包 案例 压缩 解压缩 案例 打包压缩一起...

  • 10.压缩解压类

    压缩和解压类 压缩指令gzip,解压缩指令gunzipgzip 文件 // 压缩文件,只能压缩成....

  • iOS 图片压缩总结

    一.压缩方式和方法 1.压缩方式 1.1 质量压缩1.2 尺寸压缩1.3 质量和尺寸共同压缩 2.压缩方法 2.1...

  • Linux压缩命令

    .zip格式压缩与解压缩 .gz格式压缩与解压缩 .bz2格式压缩与解压缩 打包命令tar

  • zip压缩工具、tar打包、tar打包并压缩

    65 zip压缩工具 支持压缩目录 默认不支持解压windows下的rar文件 压缩、解压缩文件 压缩、解压缩目录...

  • day14 -文件压缩

    《 文件压缩 》zip压缩 格式 压缩工具 .zip ...

网友评论

    本文标题:压缩过滤器—全站压缩

    本文链接:https://www.haomeiwen.com/subject/rynzpxtx.html