Filter之——GZIP全站压缩

时间:2022-09-20 22:55:39

     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 返回的数据。更细一点的流程如下图:Filter之——GZIP全站压缩

    

    

--------------------------------------------------------------------------------------------更新:2013年7月21日 22:34:54

Filter之——GZIP全站压缩的更多相关文章

  1. JavaWeb 后端 <十二> 之 过滤器 filter 乱码、不缓存、脏话、标记、自动登录、全站压缩过滤器

    一.过滤器是什么?有什么? 1.过滤器属于Servlet规范,从2.3版本就开始有了. 2.过滤器就是对访问的内容进行筛选(拦截).利用过滤器对请求和响应进行过滤

  2. 使用filter过滤GZIP压缩(二)

    在代码之前,讲一下用filter实现GZIP压缩的原理: 因为GZIP压缩之后,是从服务器端传输到浏览器端,从servlet到浏览器(从jsp到浏览器),其实是response带回内容,所以我们要在f ...

  3. 【Java EE 学习 19】【使用过滤器实现全站压缩】【使用ThreadLocal模式解决跨DAO事务回滚问题】

    一.使用过滤器实现全站压缩 1.目标:对网站的所有JSP页面进行页面压缩,减少用户流量的使用.但是对图片和视频不进行压缩,因为图片和视频的压缩率很小,而且处理所需要的服务器资源很大. 2.实现原理: ...

  4. 对ashx请求用Gzip,Deflated压缩

    //GZIP压缩 //查看请求头部 string acceptEncoding = context.Request.Headers["Accept-Encoding"].ToStr ...

  5. JavaScript的gzip静态压缩方法记录

    传统的JS压缩(删除注释,删除多余空格等)提供的压缩率有时还是不尽不意,幸亏现在的浏览器都支持压缩传输(通过设置http header的Content-Encoding=gzip),可以通过服务器的配 ...

  6. 基于Filter实现Gzip数据压缩

    在web开发中,当服务器端向客户端返回的数据量比较大时,我们可以通过Gzip对数据进行压缩处理 注意:如果小数据量进行压缩,压缩后的数据可能比原始数据还大:所以response返回数据量比较小时不推荐 ...

  7. spring gzip 静态压缩优化

    HTTP 压缩可以大大提高浏览网站的速度,它的原理是,在客户端请求网页后,从服务器端将网页文件压缩,再下载到客户端,由客户端的浏览器负责解压缩并浏览.相对 于普通的浏览过程HTML ,CSS,Java ...

  8. Android总结之Gzip/Zip压缩

    前言: 做过Android网络开发的都知道,在网络传输中我们一般都会开启GZIP压缩,但是出于刨根问底的天性仅仅知道如何开启就不能满足俺的好奇心的,所以想着写个demo测试一下比较常用的两个数据压缩方 ...

  9. CentOS下Apache开启Gzip网页压缩功能

    1.进入/etc/httpd/conf下打开httpd.conf文件 开启Gzip压缩功能,即去掉LoadModule deflate_module modules/mod_deflate.so这行前 ...

随机推荐

  1. php实验四

    实验四 1.创建一个Person类,Person中包含三个属性name,age,wealth,分别设置为public,private,protected,再定义Person类的子类Student. 2 ...

  2. Jmeter常用函数之__CSVRead使用

    __CSVRead函数用于对脚本进行参数话,当脚本中不同变量需要不同参数值时,可以考虑__CSVRead函数. 以登录的用户名.密码为例:实际进行压力测试时,需要模拟使用不同的用户并发访问系统,此时需 ...

  3. 如何"格式化"用过的磁带,让他被新磁带机重复利用

    1. 2.  套用翁磊的话: 勾上表示和之前的磁带信息进行协商(但是会失败), 不勾则表示强行擦除.

  4. Spring MVC之@RequestMapping 详解(转)

    引言: 前段时间项目中用到了REST风格来开发程序,但是当用POST.PUT模式提交数据时,发现服务器端接受不到提交的数据(服务器端参数绑定没有加任何注解),查看了提交方式为application/j ...

  5. gridview列显示,截取其中前面的几个字显示出来,当鼠标放上去的时候显示全部——使用LinkButton的方法

    使用LinkButton的方法<asp:LinkButton ToolTip ='<%#Eval("FilePath") %>' runat="serv ...

  6. 【Linux基础】history查看历史命令

    1.history命令 “history”命令就是历史记录.它显示了在终端中所执行过的所有命令的历史. history //显示终端执行过的命令 history //显示最近10条终端执行过的命令 C ...

  7. 最新版的Chrome不能设置网页编码怎么解?

    添加一个Google插件https://chrome.google.com/webstore/detail/set-character-encoding/bpojelgakakmcfmjfilgdlm ...

  8. Link-Cut-Tree详解

    图片参考YangZhe的论文,FlashHu大佬的博客 Link-Cut-Tree实际靠的是实链剖分,重链剖分和长链剖分珂以参考树链剖分详解 Link-Cut-Tree将某一个儿子的连边划分为实边,而 ...

  9. Nginx的安装与部署

    1:安装工具包 wget.vim和gcc yum install -y wget yum install -y vim-enhanced yum install -y make cmake gcc g ...

  10. DELL升级bios方式

    升级过程其实很简单 1.官网下载exe文件,放入U盘 2.重启电脑F12选择升级bios 3.选择U盘里面的升级文件 4.重点来了!!! boot options 是什么? 就是boot设置里面自己自 ...