【过滤器】(5)过滤器的应用案例:全站压缩技术(包装模式)
2017-08-08 17:01
453 查看
一、如何使用压缩技术
1、类:java.util.zip.GZIPOutputStream
2、格式:public class GZIPOutputStream extends DeflaterOutputStream
3、含义:此类为使用 GZIP 文件格式写入压缩数据实现流过滤器。
4、构造方法:
GZIPOutputStream(OutputStream out) 使用默认缓冲区大小创建新的输出流。
GZIPOutputStream(OutputStream out, int size) 使用指定缓冲区大小创建新的输出流。
5、方法:
void write(byte[] buf, int off, int len) 将字节数组写入压缩输出流。
二、压缩和解压的使用方式
1、测试压缩和解压类:
String str = "8月4日,由中宣部主办的党建网微平台发表了一篇以《习近平治国理政的“立与破”》为题的文章,阐述了党的十八大以来,习近平总书记围绕改革发展稳定、内政外交国防、治党治国治军发表了一系列重要讲话,确立了新形势下我们党治国理政新理念新思想新战略,彰显了立字当头、立破并举的科学导向。自2016年4月以来,学校党委认真贯彻习近平重要讲话精神,按照四个全面战略部署,结合学校实际,以直面“硬骨头”的勇气,全面推行综合改革,率先进行的“三破三立”掀开了学校改革发展的新篇章,取得了初步成效。8月4日,由中宣部主办的党建网微平台发表了一篇以《习近平治国理政的“立与破”》为题的文章,阐述了党的十八大以来,习近平总书记围绕改革发展稳定、内政外交国防、治党治国治军发表了一系列重要讲话,确立了新形势下我们党治国理政新理念新思想新战略,彰显了立字当头、立破并举的科学导向。自2016年4月以来,学校党委认真贯彻习近平重要讲话精神,按照四个全面战略部署,结合学校实际,以直面“硬骨头”的勇气,全面推行综合改革,率先进行的“三破三立”掀开了学校改革发展的新篇章,取得了初步成效。8月4日,由中宣部主办的党建网微平台发表了一篇以《习近平治国理政的“立与破”》为题的文章,阐述了党的十八大以来,习近平总书记围绕改革发展稳定、内政外交国防、治党治国治军发表了一系列重要讲话,确立了新形势下我们党治国理政新理念新思想新战略,彰显了立字当头、立破并举的科学导向。自2016年4月以来,学校党委认真贯彻习近平重要讲话精神,按照四个全面战略部署,结合学校实际,以直面“硬骨头”的勇气,全面推行综合改革,率先进行的“三破三立”掀开了学校改革发展的新篇章,取得了初步成效。"; /*压缩数据到字节数组流*/ ByteArrayOutputStream bout = new ByteArrayOutputStream(); GZIPOutputStream gzipout = new GZIPOutputStream(bout); gzipout.write(str.getBytes("utf-8")); gzipout.close(); byte[] data = bout.toByteArray(); /*解压数据到字符缓冲流*/ GZIPInputStream gzipin = new GZIPInputStream(new ByteArrayInputStream(data)); String s = null; BufferedReader br = new BufferedReader(new InputStreamReader(gzipin, "utf-8")); while((s=br.readLine())!=null){ System.out.println(s); System.out.println(s.length()); } System.out.println("压缩前字节大小:"+str.getBytes("utf-8").length); System.out.println("压缩后字节大小:"+data.length);
执行结果:
三、不用过滤器在Servlet中输出压缩数据
1、写一个FirstServlet.java,在response中压缩数据并且输出:
package cn.hncu.servlets; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.zip.GZIPOutputStream; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class FirstServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doPost(request, response); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=utf-8"); String str = "8月4日,由中宣部主办的党建网微平台发表了一篇以《习近平治国理政的“立与破”》为题的文章,阐述了党的十八大以来,习近平总书记围绕改革发展稳定、内政外交国防、治党治国治军发表了一系列重要讲话,确立了新形势下我们党治国理政新理念新思想新战略,彰显了立字当头、立破并举的科学导向。自2016年4月以来,学校党委认真贯彻习近平重要讲话精神,按照四个全面战略部署,结合学校实际,以直面“硬骨头”的勇气,全面推行综合改革,率先进行的“三破三立”掀开了学校改革发展的新篇章,取得了初步成效。8月4日,由中宣部主办的党建网微平台发表了一篇以《习近平治国理政的“立与破”》为题的文章,阐述了党的十八大以来,习近平总书记围绕改革发展稳定、内政外交国防、治党治国治军发表了一系列重要讲话,确立了新形势下我们党治国理政新理念新思想新战略,彰显了立字当头、立破并举的科学导向。自2016年4月以来,学校党委认真贯彻习近平重要讲话精神,按照四个全面战略部署,结合学校实际,以直面“硬骨头”的勇气,全面推行综合改革,率先进行的“三破三立”掀开了学校改革发展的新篇章,取得了初步成效。8月4日,由中宣部主办的党建网微平台发表了一篇以《习近平治国理政的“立与破”》为题的文章,阐述了党的十八大以来,习近平总书记围绕改革发展稳定、内政外交国防、治党治国治军发表了一系列重要讲话,确立了新形势下我们党治国理政新理念新思想新战略,彰显了立字当头、立破并举的科学导向。自2016年4月以来,学校党委认真贯彻习近平重要讲话精神,按照四个全面战略部署,结合学校实际,以直面“硬骨头”的勇气,全面推行综合改革,率先进行的“三破三立”掀开了学校改革发展的新篇章,取得了初步成效。"; //压缩字节数据 ByteArrayOutputStream bout = new ByteArrayOutputStream(); /*【注意】这里采用字节数组输出流‘内存流’*/ GZIPOutputStream gzip = new GZIPOutputStream(bout, true); gzip.write(str.getBytes("utf-8")); /*【注意】getBytes()空参的时候是GBK编码*/ gzip.close(); /*【注意】必须关流以后才可以把数据刷到bout中*/ //将压缩后的字节数据发送到前端页面 response.setHeader("Content-Encoding", "gzip"); /*【注意】响应头必须告诉浏览器这种数据要以压缩的方式解压*/ byte[] data = bout.toByteArray(); response.getOutputStream().write(data); /*【注意】向前端页面以字节流的方式输出*/ } }
2、浏览器段的响应头参数显示:页面显示的内容是经过压缩的(Content-Encoding为gzip,Content-length为509,这和我们之前测试的数据完全一致)。
四、使用过滤器在Servlet中输出压缩字节数据
1、第一步:创建过滤器并且实现三个方法:
package cn.hncu.filter; import javax.servlet.Filter; public class GzipSecondFilter implements Filter{ @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void destroy() { } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { } }
2、第二步:替换过滤器放行时候的response对象为MyResponse类对象resp:
(1)创建一个增强后的resp对象
MyResponse resp = new MyResponse((HttpServletResponse) response);
(2)将response对象用增强后的resp对象替换
chain.doFilter(request, resp);
3、第三步:用包装模式创建MyResponse类:
(3)继承response类的包装类
class MyResponse extends HttpServletResponseWrapper{ public MyResponse(HttpServletResponse response) { super(response); } }
(4)覆盖父类的getOutputStream方法
@Override public ServletOutputStream getOutputStream() throws IOException { // TODO Auto-generated method stub return super.getOutputStream(); }
(5)修改getOutputStream方法的返回值:return new MyOutputStream();
class MyOutputStream extends ServletOutputStream{ @Override public void write(int b) throws IOException { } }
(6)重新修改write方法,利用ByteArrayOutputStream的对象bout将write方法中的字节b写入到bout.write(b)中,但是bout对象必须是来自MyResponse 的参数:
class MyOutputStream extends ServletOutputStream{ private ByteArrayOutputStream bout = new ByteArrayOutputStream(); @Override public void write(int b) throws IOException { bout.write(b); } }
(7)解决方法:
(7.1)在MyOutputStream 类中声明成员变量、写构造方法接收来自MyResponse的传参:
class MyOutputStream extends ServletOutputStream{ private ByteArrayOutputStream bout; public MyOutputStream (ByteArrayOutputStream bout) { this.bout=bout; } @Override public void write(int b) throws IOException { bout.write(b); } }
(7.2)修改MyResponse类中的getOutputStream返回值表达式:
@Override public ServletOutputStream getOutputStream() throws IOException { return new MyOutputStream (bout); }
(7.3)在MyResponse中添加成员变量:
private ByteArrayOutputStream bout = new ByteArrayOutputStream();
(8)最后,对外提供一个能够获取到bout对象的方法:
public ByteArrayOutputStream getBout(){ return bout; }
4、第四步:得到MyResponse类、MyOutputStream类形成:
★★MyResponse类:★★
class MyResponse extends HttpServletResponseWrapper{
/*【注意】给包装类配的一个容器,用于存储后台发送的数据,以用在过滤器取出来进行压缩输出到客户端。*/
private ByteArrayOutputStream bout = new ByteArrayOutputStream();
public MyResponse(HttpServletResponse response) {
super(response);
}
@Override
public ServletOutputStream getOutputStream() throws IOException {
return new MyOutputStream(bout);
}
public ByteArrayOutputStream getBout(){ return bout; }
}
★★MyOutputStream 类:★★
class MyOutputStream extends ServletOutputStream{ private ByteArrayOutputStream bout ; public MyOutputStream(ByteArrayOutputStream bout) { this.bout=bout; } @Override public void write(int b) throws IOException { bout.write(b); } }
5、第五步:最后依旧是正常的压缩数据并且输出:
/*【注意】增强完response类后继续放行*/ chain.doFilter(request, resp); /*【注意】放行以后获取response中的数据并且压缩*/ ByteArrayOutputStream srcData = resp.getBout();/*【注意】srcData是压缩前的数据*/ byte[] srcDatas = srcData.toByteArray(); ByteArrayOutputStream bout = new ByteArrayOutputStream(); GZIPOutputStream gzip = new GZIPOutputStream(bout, true); gzip.write(srcDatas); gzip.close(); /*【注意】压缩完以后将数据发送到前端页面*/ HttpServletResponse httpResp = (HttpServletResponse) response; httpResp.setHeader("Content-Encoding", "gzip"); httpResp.getOutputStream().write(bout.toByteArray());
五、使用过滤器在Servlet中输出压缩字符数据
package cn.hncu.filter; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStreamWriter; import java.io.PrintWriter; 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.HttpServletResponse; import javax.servlet.http.HttpServletResponseWrapper; public class GzipThirdFilter implements Filter{ @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void destroy() { } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { /*【注意】在放行前对response类进行增强*/ MyResponse2 resp = new MyResponse2((HttpServletResponse)response); /*【注意】将response类增强以后放行*/ chain.doFilter(request, resp); /*【注意】放行以后将从增强后的类中获取源数据*/ ByteArrayOutputStream srcData = resp.getBout(); byte[] datas = srcData.toByteArray(); ByteArrayOutputStream bout = new ByteArrayOutputStream(); GZIPOutputStream gzip = new GZIPOutputStream(bout, true); gzip.write(datas); gzip.close(); /*【注意】将压缩后的数据发送到前端页面*/ HttpServletResponse httpResponse = (HttpServletResponse) response; httpResponse.setHeader("Content-Encoding", "gzip"); httpResponse.getOutputStream().write(bout.toByteArray()); response.getOutputStream().println(); response.getWriter().println(); } } class MyResponse2 extends HttpServletResponseWrapper{ private ByteArrayOutputStream bout = new ByteArrayOutputStream(); private PrintWriter writer= null; public MyResponse2(HttpServletResponse response) { super(response); } @Override public PrintWriter getWriter() throws IOException { /*【注意】因为PrintWriter的构造方法本身就有套结的方式,因此直接把bout套结上去就可以了,不用像字节流那样还要增强2层*/ writer= new PrintWriter(new OutputStreamWriter(bout,"utf-8"), true); return writer; } public ByteArrayOutputStream getBout(){ if(writer!=null){ writer.close();/*【注意】必须关流*/ } return bout; } }
六、将压缩字节、压缩字符结合起来,形成全站压缩
package cn.hncu.all.filter; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.util.zip.GZIPOutputStream; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletOutputStream; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponseWrapper; public class GzipFilter implements Filter{ @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { /*【注意】放行前增强response类 */ MyResponse resp = new MyResponse((HttpServletResponse) response); /*【注意】增强完response类后继续放行*/ chain.doFilter(request, resp); /*【注意】放行以后获取response中的数据并且压缩*/ ByteArrayOutputStream srcData = resp.getBout();/*【注意】srcData是压缩前的数据*/ byte[] srcDatas = srcData.toByteArray(); ByteArrayOutputStream bout = new ByteArrayOutputStream(); GZIPOutputStream gzip = new GZIPOutputStream(bout, true); gzip.write(srcDatas); gzip.close(); /*【注意】压缩完以后将数据发送到前端页面*/ HttpServletResponse httpResp = (HttpServletResponse) response; httpResp.setHeader("Content-Encoding", "gzip"); httpResp.getOutputStream().write(bout.toByteArray()); } @Override public void destroy() { } } class MyResponse extends HttpServletResponseWrapper{ /*【注意】给包装类配的一个容器,用于存储后台发送的数据,以用在过滤器取出来进行压缩输出到客户端。*/ private ByteArrayOutputStream bout = new ByteArrayOutputStream(); private PrintWriter writer= null; public MyResponse(HttpServletResponse response) { super(response); } @Override public ServletOutputStream getOutputStream() throws IOException { return new MyOutputStream(bout); } @Override public PrintWriter getWriter() throws IOException { /*【注意】因为PrintWriter的构造方法本身就有套结的方式,因此直接把bout套结上去就可以了,不用像字节流那样还要增强2层*/ writer= new PrintWriter(new OutputStreamWriter(bout,"utf-8"), true); return writer; } public ByteArrayOutputStream getBout(){ if(writer!=null){ writer.close();/*【注意】必须关流*/ } return bout; } } class MyOutputStream extends ServletOutputStream{ private ByteArrayOutputStream bout ; public MyOutputStream(ByteArrayOutputStream bout) { this.bout=bout; } @Override public void write(int b) throws IOException { bout.write(b); } }
相关文章推荐
- 【过滤器】(4)过滤器的应用案例:留言板敏感词过滤技术(包装模式)
- 解决全站乱码的过滤器实现-包装类设计模式的应用
- 全站压缩---(装饰模式、过滤器的应用)
- 过滤器和包装类设计模式的应用
- 过滤器和包装类设计模式的应用
- 【过滤器】(3)过滤器的应用案例:网站自动登录技术(Cookie记忆)
- web day21 web过滤器Filter,应用案例统计IP,解决全站乱码,粗粒度权限控制,页面静态化
- 【过滤器】(2)过滤器的应用案例:网站安全登录技术
- 【Java EE 学习 19】【使用过滤器实现全站压缩】【使用ThreadLocal模式解决跨DAO事务回滚问题】
- 过滤器(Filter)应用:全站压缩----Gzip网页压缩输出
- 过滤器Filter的案例4——实现全站的数据的压缩
- 过滤器应用之全站压缩
- Java_Web学习笔记_过滤器应用案例(解决全站字符乱码)
- Java Web开发技术应用——过滤器
- 责任链设计模式应用场景示例(过滤器、拦截器)
- MVC4商城项目四:应用Bundle捆绑压缩技术
- 高可用集群技术之heartbeat应用案例详解(二)
- 企业应用开发模式 ERP项目中应用到的技术和工具
- IGMPv3广播电视网络应用案例之PIM-SSM技术
- JavaWeb学习篇——使用过滤器及装饰器设计模式解决全站乱码问题