Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2321095
  • 博文数量: 252
  • 博客积分: 5472
  • 博客等级: 大校
  • 技术积分: 3107
  • 用 户 组: 普通用户
  • 注册时间: 2011-09-17 18:39
文章分类

全部博文(252)

文章存档

2012年(96)

2011年(156)

分类: 系统运维

2011-12-15 17:02:20

目前主流的浏览器和Web服务器都支持网页的压缩  浏览器和Web服务器对于压缩网页通信过程如下
 
#  如果浏览器能够接受压缩后的网页内容 那么他会在请求中发送Accept-Encoding请求报头 值为"gzip.deflate"  表明浏览器支持gzip和deflate这两种压缩方式
 
#  Web服务器读取Accept-Encoding请求报头的值来判断浏览器是否接受压缩的内容 如果接受 Web服务器就讲目标页面的响应内容采用gzip压缩方式压缩后再发送到客户端 同时设置Content-Encoding实体报头 值为gzip 以告知浏览器实体正文采用了gzip的压缩编码
 
#  浏览器接收到响应内容后 根据Content-Encoding实体报头的值对响应内容解压缩 然后显示相应页面的内容
 
 
我们可以通过过滤器对目标内容进行压缩 是吸纳原理就是实用包装类对象替换原始响应对象  并使用java.util.zip.GZIPOutputStream作为响应内容的输出流对象  GZIPOutputStream是是过滤流类 他使用GZIP压缩格式写入压缩对象
 
步骤
 
1  GZIPServletOutputStream.java
GZIPStreamOutputStream继承自ServletOutputStream  该类的对象用于替换HttpServletResponse.getOutputStream()方法返回的ServletOutputStream对象  其内部使用GZIPOutputStream的write(int b)方法实现ServletOutputStream类的write(int b)方法 以达到压缩数据的目的
  1. package filter;

  2. import java.io.IOException;
  3. import java.util.zip.GZIPOutputStream;

  4. import javax.servlet.ServletOutputStream;

  5. public class GZIPServletOutputStream extends ServletOutputStream
  6. {
  7.     private GZIPOutputStream gzipos;
  8.     public GZIPServletOutputStream(ServletOutputStream sos) throws IOException
  9.     {
  10.         //使用响应输出流对象构造GZIPOutputStream过滤流对象

  11.         this.gzipos = new GZIPOutputStream(sos);        
  12.     }
  13.     @Override
  14.     public void write(int data) throws IOException
  15.     {
  16.         //将写入操作委托给GZIPOutputStream对象的write()方法,从而实现响应输出流的压缩

  17.         gzipos.write(data);
  18.     }
  19.     
  20.     /**
  21.      * 返回GZIPOutputStream对象,过滤器需要访问这个对象,以便完成将压缩数据写入输出流的操作
  22.      */
  23.     public GZIPOutputStream getGZIPOutputStream()
  24.     {
  25.         return gzipos;
  26.     }
  27. }

 

2  CompressionResponseWrapper.java

CompressionResponseWrapper类从HttpServletWrapper类继承  重写了getWriter()和getOutputStream()方法  用GZIPServletOutputStream替换了ServletOutputStream对象

 

  1. package filter;

  2. import java.io.IOException;
  3. import java.io.PrintWriter;
  4. import java.util.zip.GZIPOutputStream;

  5. import javax.servlet.ServletOutputStream;
  6. import javax.servlet.http.HttpServletResponse;
  7. import javax.servlet.http.HttpServletResponseWrapper;

  8. public class CompressionResponseWrapper extends HttpServletResponseWrapper
  9. {

  10.     private GZIPServletOutputStream gzipsos;
  11.     private PrintWriter pw;
  12.     
  13.     public CompressionResponseWrapper(HttpServletResponse response) throws IOException
  14.     {
  15.         super(response);
  16.         
  17.         //用响应输出流创建GZIPServletOutputStream对象

  18.         gzipsos = new GZIPServletOutputStream(response.getOutputStream());
  19.         ////用GZIPServletOutputStream对象作为参数,构造PrintWriter对象

  20.         pw = new PrintWriter(gzipsos);
  21.     }
  22.     
  23.     /**
  24.      * 重写setContentLength()方法,以避免Content-Length实体报头所指出的长度
  25.      * 和压缩后的实体正文长度不匹配
  26.      */
  27.     @Override
  28.     public void setContentLength(int len){}

  29.     @Override
  30.     public ServletOutputStream getOutputStream() throws IOException
  31.     {
  32.         return gzipsos;
  33.     }

  34.     @Override
  35.     public PrintWriter getWriter() throws IOException
  36.     {
  37.         return pw;
  38.     }
  39.     
  40.     /**
  41.      * 过滤器调用这个方法来得到GZIPOutputStream对象,以便完成将压缩数据写入输出流的操作
  42.      */
  43.     public GZIPOutputStream getGZIPOutputStream()
  44.     {
  45.         return gzipsos.getGZIPOutputStream();
  46.     }
  47. }

 

3  CompressionFilter.java

是过滤器类  使用CompressionResponseWrapper对象来实现对响应内容的压缩

 

  1. package filter;

  2. import java.io.IOException;
  3. import java.util.zip.GZIPOutputStream;

  4. import javax.servlet.Filter;
  5. import javax.servlet.FilterChain;
  6. import javax.servlet.FilterConfig;
  7. import javax.servlet.ServletException;
  8. import javax.servlet.ServletRequest;
  9. import javax.servlet.ServletResponse;
  10. import javax.servlet.http.HttpServletRequest;
  11. import javax.servlet.http.HttpServletResponse;

  12. public class CompressionFilter implements Filter
  13. {
  14.     public void init(FilterConfig filterConfig) throws ServletException{}

  15.     public void destroy(){}

  16.     @Override
  17.     public void doFilter(ServletRequest request, ServletResponse response,
  18.             FilterChain chain) throws IOException, ServletException
  19.     {
  20.         HttpServletRequest httpReq = (HttpServletRequest) request;
  21.         HttpServletResponse httpResp = (HttpServletResponse) response;

  22.         String acceptEncodings = httpReq.getHeader("Accept-Encoding");
  23.         if (acceptEncodings != null && acceptEncodings.indexOf("gzip") > -1)
  24.         {
  25.             // 得到响应对象的封装类对象

  26.             CompressionResponseWrapper respWrapper = new CompressionResponseWrapper(
  27.                     httpResp);
  28.             
  29.             // 设置Content-Encoding实体报头,告诉浏览器实体正文采用了gzip压缩编码

  30.             respWrapper.setHeader("Content-Encoding", "gzip");
  31.             chain.doFilter(httpReq, respWrapper);
  32.             
  33.             //得到GZIPOutputStream输出流对象

  34.             GZIPOutputStream gzipos = respWrapper.getGZIPOutputStream();
  35.             //调用GZIPOutputStream输出流对象的finish()方法完成将压缩数据写入

  36.             //响应输出流的操作,无须关闭输出流

  37.             gzipos.finish();
  38.         }
  39.         else
  40.         {
  41.             chain.doFilter(httpReq, httpResp);
  42.         }

  43.     }
  44. }

4   添加CompressionFilter的xml配置

注意 CompressionFilter过滤器的配置应该放在GuestbookFilter过滤器的前面

 

  1. <filter>
  2.         <filter-name>CompressionFilter</filter-name>
  3.         <filter-class>filter.CompressionFilter</filter-class>
  4.     </filter>
  5.     
  6.     
  7.     <filter-mapping>
  8.         <filter-name>CompressionFilter</filter-name>
  9.         <url-pattern>*.jsp</url-pattern>
  10.         <url-pattern>*.html</url-pattern>
  11.     </filter-mapping>

 

5  实验测试

看页面感觉不到CompressionFilter过滤器是否起作用了

在命令提示符窗口中输入:

telnet localhost 8080

然后再输入:

 

  1. GET /GZIPFilter/index.jsp HTTP/1.1
  2. Host:localhost
  3. Accept-Encoding:gzip

连续输入两次回车后 如果看到一堆乱码 就说明CompressionFilter过滤器已经起作用了

 

 

======================================

这个例子很难啊 没怎么看懂

阅读(2862) | 评论(5) | 转发(2) |
给主人留下些什么吧!~~

xueliangfei2011-12-29 19:54:20

灯泡代表我的心: 感觉压缩有时候就是放入一个文件夹打包了一下~.....
恩 是呀

灯泡代表我的心2011-12-29 09:55:50

感觉压缩有时候就是放入一个文件夹打包了一下~

xueliangfei2011-12-22 09:07:34

鸪灵: 过滤器会直接进行压缩?.....
恩 你觉得呢?

xueliangfei2011-12-20 11:01:15

鸪灵: 过滤器会直接进行压缩?.....

鸪灵2011-12-20 05:23:24

过滤器会直接进行压缩?