zoukankan      html  css  js  c++  java
  • Gzip压缩优化网站

    网站常使用GZIP压缩算法对网页内容进行压缩,然后传给浏览器,以减小数据传输量,提高响应速度。浏览器接收到GZIP压缩数据后会自动解压并正确显示。GZIP加速常用于解决网速慢的瓶颈。

    压缩Filter中需要先判断客户浏览器时候支持GZip自动解压,如果支持,则进行GZIP压缩,否则不压缩。判断的依据是浏览器提供的Header信息,代码如下:

    GZipFilter.java

     1package com.rom.util;
     2  
     3 import java.io.IOException;
     4  
     5 import javax.servlet.Filter;
     6 import javax.servlet.FilterChain;
     7 import javax.servlet.FilterConfig;
     8 import javax.servlet.ServletException;
     9 import javax.servlet.ServletRequest;
    10 import javax.servlet.ServletResponse;
    11 import javax.servlet.http.HttpServletRequest;
    12 import javax.servlet.http.HttpServletResponse;
    13  
    14 /**
    15  * Servlet Filter implementation class GzipFilter
    16  */
    17 public class GzipFilter implements Filter {
    18  
    19     /**
    20      * Default constructor.
    21      */
    22     public GzipFilter() {
    23         // TODO Auto-generated constructor stub
    24     }
    25  
    26     /**
    27      * @see Filter#destroy()
    28      */
    29     public void destroy() {
    30         // TODO Auto-generated method stub
    31     }
    32  
    33     /**
    34      * @see Filter#doFilter(ServletRequest, ServletResponse, FilterChain)
    35      */
    36     public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) {
    37         // TODO Auto-generated method stub
    38         // place your code here
    39  
    40         System.out.println("压缩的");
    41  
    42  
    43         // TODO Auto-generated method stub 
    44         HttpServletRequest request = (HttpServletRequest)req; 
    45         HttpServletResponse response =(HttpServletResponse)res; 
    46  
    47         String acceptEncoding =request.getHeader("Accept-Encoding"); 
    48         //支持的编码方式 
    49  
    50         try {
    51             if(acceptEncoding != null && acceptEncoding.toLowerCase().indexOf("gzip") != -1){ 
    52  
    53                 System.out.println("执行压缩的方法");
    54  
    55                 //如果客户浏览器支持GZIP格式,则使用GZIP压缩数据 
    56                 GZipResponseWrapper gzipRes = new GZipResponseWrapper(response); 
    57  
    58                 chain.doFilter(request, gzipRes);//doFilter,使用自定义的response 
    59                 gzipRes.finishResponse();//输出压缩数据 
    60  
    61             }else{ 
    62                 System.out.println("没有压缩");
    63  
    64                 chain.doFilter(request, response);//否则不压缩 
    65             } 
    66 //          chain.doFilter(request, response);
    67         } catch (IOException e) {
    68             e.printStackTrace();
    69         } catch (ServletException e) {
    70             e.printStackTrace();
    71         }
    72     }
    73  
    74     /**
    75      * @see Filter#init(FilterConfig)
    76      */
    77     public void init(FilterConfig fConfig) throws ServletException {
    78         // TODO Auto-generated method stub
    79     }
    80  
    81 }

    GZipResponseWrapper为自定义的response类,内部将对输出的内容进行GZIP压缩。它集成HttpServletResponseWrapper类,也是一个“伪装”的response,不真正输出内容到客户端。

    GZipResponseWrapper.java

     1 package com.rom.util;
     2  
     3 import java.io.IOException;
     4 import java.io.OutputStreamWriter;
     5 import java.io.PrintWriter;
     6  
     7 import javax.servlet.ServletOutputStream;
     8 import javax.servlet.http.HttpServletResponse;
     9 import javax.servlet.http.HttpServletResponseWrapper;
    10  
    11 public class GZipResponseWrapper extends HttpServletResponseWrapper {
    12      // 默认的 response 
    13     private HttpServletResponse response; 
    14  
    15     // 自定义的 outputStream, 执行close()的时候对数据压缩,并输出 
    16     private GZipOutputStream gzipOutputStream; 
    17  
    18     // 自定义 printWriter,将内容输出到 GZipOutputStream 中 
    19     private PrintWriter writer; 
    20  
    21     public GZipResponseWrapper(HttpServletResponse response) throws IOException { 
    22         super(response); 
    23         this.response = response; 
    24     } 
    25  
    26     public ServletOutputStream getOutputStream() throws IOException { 
    27         if (gzipOutputStream == null) 
    28             gzipOutputStream = new GZipOutputStream(response); 
    29         return gzipOutputStream; 
    30     } 
    31  
    32     public PrintWriter getWriter() throws IOException { 
    33         if (writer == null) 
    34             writer = new PrintWriter(new OutputStreamWriter( 
    35                     new GZipOutputStream(response), "UTF-8")); 
    36         return writer; 
    37     } 
    38  
    39     // 压缩后数据长度会发生变化 因此将该方法内容置空 
    40     public void setContentLength(int contentLength) { 
    41     } 
    42  
    43     public void flushBuffer() throws IOException { 
    44         gzipOutputStream.flush(); 
    45     } 
    46  
    47     public void finishResponse() throws IOException { 
    48         if (gzipOutputStream != null) 
    49             gzipOutputStream.close(); 
    50         if (writer != null) 
    51             writer.close(); 
    52     } 
    53 }

    getWriter()与getOutputStream()都使用了GZipOutputStream类。这是自定义的一个ServletOutputStream类,它先将数据缓存起来,然后使用JDK自带的GZIP压缩类将数据压缩,并输出到客户端浏览器。GZIP数据压缩与输出都在该类里实现的。

    GZipOutputStream.java

     1 package com.rom.util;
     2  
     3 import java.io.ByteArrayOutputStream;
     4 import java.io.IOException;
     5 import java.util.zip.GZIPOutputStream;
     6  
     7 import javax.servlet.ServletOutputStream;
     8 import javax.servlet.http.HttpServletResponse;
     9  
    10 public class GZipOutputStream extends ServletOutputStream {
    11  
    12      private HttpServletResponse response; 
    13  
    14  
    15         private GZIPOutputStream gzipOutputStream; 
    16  
    17  
    18         private ByteArrayOutputStream byteArrayOutputStream; 
    19  
    20         public GZipOutputStream(HttpServletResponse response) throws IOException { 
    21             this.response = response; 
    22             byteArrayOutputStream = new ByteArrayOutputStream(); 
    23             gzipOutputStream = new GZIPOutputStream(byteArrayOutputStream); 
    24         } 
    25  
    26         public void write(int b) throws IOException { 
    27             gzipOutputStream.write(b); 
    28         } 
    29  
    30         public void close() throws IOException { 
    31  
    32  
    33             gzipOutputStream.finish(); 
    34  
    35  
    36             byte[] content = byteArrayOutputStream.toByteArray(); 
    37  
    38  
    39             response.addHeader("Content-Encoding", "gzip"); 
    40             response.addHeader("Content-Length", Integer.toString(content.length)); 
    41  
    42  
    43             ServletOutputStream out = response.getOutputStream(); 
    44             out.write(content); 
    45             out.close(); 
    46         } 
    47  
    48         public void flush() throws IOException { 
    49             gzipOutputStream.flush(); 
    50         } 
    51  
    52         public void write(byte[] b, int off, int len) throws IOException { 
    53             gzipOutputStream.write(b, off, len); 
    54         } 
    55  
    56         public void write(byte[] b) throws IOException { 
    57             gzipOutputStream.write(b); 
    58         } 
    59  
    60 }

    添加xml配置文件

    1  <filter>
    2   <display-name>GzipFilter</display-name>
    3   <filter-name>GzipFilter</filter-name>
    4   <filter-class>com.rom.util.GzipFilter</filter-class>
    5 </filter>
    6 <filter-mapping>
    7   <filter-name>GzipFilter</filter-name>
    8   <url-pattern>/*</url-pattern>
    9 </filter-mapping>
  • 相关阅读:
    《深入理解 Java 虚拟机》读书笔记:线程安全与锁优化
    《深入理解 Java 虚拟机》读书笔记:Java 内存模型与线程
    《深入理解 Java 虚拟机》读书笔记:晚期(运行期)优化
    《深入理解 Java 虚拟机》读书笔记:早期(编译期)优化
    《深入理解 Java 虚拟机》读书笔记:虚拟机字节码执行引擎
    《深入理解 Java 虚拟机》读书笔记:虚拟机类加载机制
    Java学习书籍推荐
    IntelliJ IDEA之新建项目后之前的项目不见了
    剑指Offer之左旋转字符串
    剑指Offer之和为S的两个数字
  • 原文地址:https://www.cnblogs.com/zfy0098/p/5566562.html
Copyright © 2011-2022 走看看