您的位置:首页 > 其它

【过滤器】(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);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: