GZIP压缩提高网络传输效率

【spring】通过GZIP压缩提高网络传输效率(可以实现任何资源的gzip压缩、包括AJAX)

gzip是http协议中使用的一种加密算法,客户端向web服务器端发出了请求后,通常情况下服务器端会将页面文件和其他资源,返回到客户端,客户端加载后渲染呈现,这种情况文件一般都比较大,如果开启Gzip ,那么服务器端响应后,会将页面,JS,CSS等文本文件或者其他文件通过高压缩算法将其压缩,然后传输到客户端,由客户端的浏览器负责解压缩与呈现。通常能节省40%以上的流量(一般都有60%左右),一些PHP,JSP文件也能够进行压缩。

1、通过WEB服务器打开GZIP压缩服务

      目前大多数主流WEB中间件都支持GZIP压缩、下面以Tomcat 为例进行说明:

      找到Tomcat 目录下的conf下的server.xml,并找到如下信息

      <Connector port = "8080" maxHttpHeaderSize = "8192" maxThreads = "150" minSpareThreads = "25"
              maxSpareThreads = "75" enableLookups = "false" redirectPort = "8443" acceptCount = "100"
              connectionTimeout = "20000" disableUploadTimeout = "true"

      将它改成如下的形式(其实在上面代码的下面已经有了,将他们打开而已。):

      <Connector port="8080" maxHttpHeaderSize="8192" maxThreads="150" minSpareThreads="25"
             maxSpareThreads="75" enableLookups="false" redirectPort="8443" acceptCount="100"
             connectionTimeout="20000" disableUploadTimeout="true"
             compression="on" compressionMinSize="2048" noCompressionUserAgents="gozilla, traviata"
             compressableMimeType="text/html,text/xml" >

      这样,就能够对html和xml进行压缩了,如果要压缩css 和 js,那么需要将

           compressableMimeType=”text/html,text/xml”加入css和js:

           <Connector port="8080" ......... compressableMimeType="text/html,text/xml,text/css,text/javascript" >

      一般文本类型的静态文件可以通过这种方式压缩后传输、提高传输效率。

      已压缩过的静态文件(如图片)进行gzip压缩后大小基本无变化、所以一般不进行压缩。

2、通过过滤器实现gzip压缩

[java] view plain copy
 
  1. package com.tyyd.framework.web;  
  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.ServletOutputStream;  
  10. import javax.servlet.ServletRequest;  
  11. import javax.servlet.ServletResponse;  
  12. import javax.servlet.http.HttpServletRequest;  
  13. import javax.servlet.http.HttpServletResponse;  
  14.   
  15. import org.apache.commons.io.FilenameUtils;  
  16. import org.apache.commons.lang.StringUtils;  
  17.   
  18. import com.tyyd.framework.core.AcwsInfo;  
  19. import com.tyyd.framework.core.AcwsMonitorLog;  
  20. import com.tyyd.framework.core.BufferedResponse;  
  21. import com.tyyd.framework.core.util.ZipUtil;  
  22.    
  23. /** 
  24.  * HTTP访问过滤器 
  25.  */  
  26. public class PageVisitFilter2 implements Filter {  
  27.    
  28.     @Override  
  29.     public void init(FilterConfig filterConfig) throws ServletException {  
  30.     }  
  31.    
  32.     @Override  
  33.     public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {  
  34.         //性能监控  
  35.         long startTime = System.currentTimeMillis();  
  36.                   
  37.         HttpServletRequest request = (HttpServletRequest)req;  
  38.         HttpServletResponse response = (HttpServletResponse)res;  
  39.           
  40.         String uri = request.getRequestURI();  
  41.         String ext = FilenameUtils.getExtension(uri);  
  42.           
  43.         try{  
  44.             response.setHeader("Pragma", "No-cache");  
  45.             response.setHeader("Cache-Control", "no-cache");  
  46.             response.setDateHeader("Expires", -1);  
  47.             request.setCharacterEncoding("UTF-8");  
  48.             response.setCharacterEncoding("UTF-8");  
  49.               
  50.             response.setHeader("renderer", "webkit");   
  51.             response.setHeader("viewport", "width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0 user-scalable=no");   
  52.       
  53.             if(isGZipEncoding(request)){  
  54.                 //需要过滤的扩展名:.htm,.html,.jsp,.js,.ajax,.css  
  55.                 String gzippPattern=",.htm,.html,.jsp,.js,.ajax,.css,";  
  56.                 if(StringUtils.indexOf(gzippPattern, ",."+ext+",")!=-1){  
  57.                     BufferedResponse gzipResponse = new BufferedResponse(response);  
  58.                     chain.doFilter(request, gzipResponse);  
  59.                     byte[] srcData = gzipResponse.getResponseData();  
  60.                     byte[] outData = null;  
  61.                     if(srcData.length > 512){  
  62.                         byte[] gzipData = ZipUtil.toGzipBytes(srcData);  
  63.                         response.addHeader("Content-Encoding", "gzip");  
  64.                         response.setContentLength(gzipData.length);  
  65.                         outData = gzipData;  
  66.                     } else {  
  67.                         outData = srcData;  
  68.                     }  
  69.                     ServletOutputStream output = response.getOutputStream();  
  70.                     output.write(outData);  
  71.                     output.flush();               
  72.                 } else {  
  73.                     chain.doFilter(request, response);  
  74.                 }  
  75.                 return;  
  76.             }  
  77.               
  78.             chain.doFilter(request, response);  
  79.         }catch(Exception e){  
  80.           
  81.         }finally{  
  82.             AcwsMonitorLog.warnHttpVisit(startTime, request);  
  83.         }  
  84.     }  
  85.    
  86.     @Override  
  87.     public void destroy() {  
  88.     }  
  89.       
  90.     /** 
  91.      * 判断浏览器是否支持GZIP 
  92.      * @param request 
  93.      * @return  
  94.      */  
  95.     private boolean isGZipEncoding(HttpServletRequest request){  
  96.       boolean flag=false;  
  97.       String encoding=request.getHeader("Accept-Encoding");  
  98.       if(encoding.indexOf("gzip")!=-1){  
  99.         flag=true;  
  100.       }  
  101.       return flag;  
  102.     }   
  103. }  
[java] view plain copy
 
  1. package com.tyyd.framework.core;  
  2.   
  3.   
  4. import java.io.IOException;  
  5. import java.io.OutputStreamWriter;  
  6. import java.io.PrintWriter;  
  7.   
  8. import javax.servlet.ServletOutputStream;  
  9. import javax.servlet.http.HttpServletResponse;  
  10. import javax.servlet.http.HttpServletResponseWrapper;  
  11.   
  12. public class BufferedResponse extends HttpServletResponseWrapper {  
  13.     public static final int OT_NONE = 0, OT_WRITER = 1, OT_STREAM = 2;  
  14.       
  15.     private BufferedOutputStream outputStream = null;  
  16.     private PrintWriter writer = null;  
  17.     private int outputType = OT_NONE;  
  18.   
  19.     public BufferedResponse(HttpServletResponse response) {  
  20.         super(response);  
  21.         outputStream = new BufferedOutputStream();  
  22.     }  
  23.       
  24.     public PrintWriter getWriter() throws IOException {  
  25.         if (outputType == OT_STREAM)  
  26.             throw new IllegalStateException();  
  27.         else if (outputType == OT_WRITER)  
  28.             return writer;  
  29.         else {  
  30.             outputType = OT_WRITER;  
  31.             writer = new PrintWriter(new OutputStreamWriter(outputStream,  
  32.                     getCharacterEncoding()), true);  
  33.             return writer;  
  34.         }  
  35.     }  
  36.       
  37.     public ServletOutputStream getOutputStream() throws IOException {  
  38.         if (outputType == OT_WRITER)  
  39.             throw new IllegalStateException();  
  40.         else if (outputType == OT_STREAM)  
  41.             return outputStream;  
  42.         else {  
  43.             outputType = OT_STREAM;  
  44.             return outputStream;  
  45.         }  
  46.     }  
  47.     public void flushBuffer() throws IOException {  
  48.         try{writer.flush();}catch(Exception e){}  
  49.         try{outputStream.flush();}catch(Exception e){}  
  50.     }  
  51.   
  52.     public void reset() {  
  53.         outputType = OT_NONE;  
  54.         outputStream.reset();  
  55.     }  
  56.   
  57.     public byte[] getResponseData() throws IOException {  
  58.         flushBuffer();  
  59.         return outputStream.toByteArray();  
  60.     }  
  61. }  
[java] view plain copy
 
  1. /** 
  2.  * 版权所有: 
  3.  * 项目名称:框架 
  4.  * 创建者: Wangdf 
  5.  * 创建日期: 2015-2-27 
  6.  * 文件说明: AJAX 缓存输出流 
  7.  */  
  8. package com.tyyd.framework.core;  
  9.   
  10. import java.io.ByteArrayOutputStream;  
  11. import java.io.IOException;  
  12.   
  13. import javax.servlet.ServletOutputStream;  
  14.   
  15. public class BufferedOutputStream extends ServletOutputStream {  
  16.     private ByteArrayOutputStream outputStream = null;  
  17.   
  18.     public BufferedOutputStream(){  
  19.         outputStream = new ByteArrayOutputStream(1024);  
  20.     }  
  21.       
  22.       
  23.     /** 
  24.      * Writes the specified byte to this output stream. The general  
  25.      * contract for <code>write</code> is that one byte is written  
  26.      * to the output stream. The byte to be written is the eight  
  27.      * low-order bits of the argument <code>b</code>. The 24  
  28.      * high-order bits of <code>b</code> are ignored. 
  29.      * <p> 
  30.      * Subclasses of <code>OutputStream</code> must provide an  
  31.      * implementation for this method.  
  32.      * 
  33.      * @param      b   the <code>byte</code>. 
  34.      * @exception  IOException  if an I/O error occurs. In particular,  
  35.      *             an <code>IOException</code> may be thrown if the  
  36.      *             output stream has been closed. 
  37.      */  
  38.     public void write(int b) throws IOException {  
  39.         outputStream.write(b);  
  40.     }  
  41.   
  42.     /** 
  43.      * Writes <code>b.length</code> bytes from the specified byte array  
  44.      * to this output stream. The general contract for <code>write(b)</code>  
  45.      * is that it should have exactly the same effect as the call  
  46.      * <code>write(b, 0, b.length)</code>. 
  47.      * 
  48.      * @param      b   the data. 
  49.      * @exception  IOException  if an I/O error occurs. 
  50.      * @see        java.io.OutputStream#write(byte[], int, int) 
  51.      */  
  52.     public void write(byte b[]) throws IOException {  
  53.         outputStream.write(b);  
  54.     }  
  55.   
  56.     /** 
  57.      * Writes <code>len</code> bytes from the specified byte array  
  58.      * starting at offset <code>off</code> to this output stream.  
  59.      * The general contract for <code>write(b, off, len)</code> is that  
  60.      * some of the bytes in the array <code>b</code> are written to the  
  61.      * output stream in order; element <code>b[off]</code> is the first  
  62.      * byte written and <code>b[off+len-1]</code> is the last byte written  
  63.      * by this operation. 
  64.      * <p> 
  65.      * The <code>write</code> method of <code>OutputStream</code> calls  
  66.      * the write method of one argument on each of the bytes to be  
  67.      * written out. Subclasses are encouraged to override this method and  
  68.      * provide a more efficient implementation.  
  69.      * <p> 
  70.      * If <code>b</code> is <code>null</code>, a  
  71.      * <code>NullPointerException</code> is thrown. 
  72.      * <p> 
  73.      * If <code>off</code> is negative, or <code>len</code> is negative, or  
  74.      * <code>off+len</code> is greater than the length of the array  
  75.      * <code>b</code>, then an <tt>IndexOutOfBoundsException</tt> is thrown. 
  76.      * 
  77.      * @param      b     the data. 
  78.      * @param      off   the start offset in the data. 
  79.      * @param      len   the number of bytes to write. 
  80.      * @exception  IOException  if an I/O error occurs. In particular,  
  81.      *             an <code>IOException</code> is thrown if the output  
  82.      *             stream is closed. 
  83.      */  
  84.     public void write(byte b[], int off, int len) throws IOException {  
  85.         outputStream.write(b, off, len);  
  86.     }  
  87.     /** 
  88.      * Writes a <code>String</code> to the client,  
  89.      * without a carriage return-line feed (CRLF)  
  90.      * character at the end. 
  91.      * 
  92.      * 
  93.      * @param s         the <code>String</code> to send to the client 
  94.      * 
  95.      * @exception IOException   if an input or output exception occurred 
  96.      * 
  97.      */  
  98.     public void print(String s) throws IOException {  
  99.         print(s, "UTF-8");  
  100.     }  
  101.   
  102.     public void print(String s, String charsetName) throws IOException {  
  103.         /* 
  104.          * 解决中文乱码问题 
  105.          */  
  106.         outputStream.write(s.getBytes(charsetName));  
  107.     }  
  108.   
  109.   
  110.   
  111.     /** 
  112.      * Writes a <code>boolean</code> value to the client, 
  113.      * with no carriage return-line feed (CRLF)  
  114.      * character at the end. 
  115.      * 
  116.      * @param b         the <code>boolean</code> value  
  117.      *              to send to the client 
  118.      * 
  119.      * @exception IOException   if an input or output exception occurred 
  120.      * 
  121.      */  
  122.   
  123.     public void print(boolean b) throws IOException {  
  124.         print(b?"true":"false");  
  125.     }  
  126.   
  127.   
  128.   
  129.     /** 
  130.      * Writes a character to the client, 
  131.      * with no carriage return-line feed (CRLF)  
  132.      * at the end. 
  133.      * 
  134.      * @param c         the character to send to the client 
  135.      * 
  136.      * @exception IOException   if an input or output exception occurred 
  137.      * 
  138.      */  
  139.   
  140.     public void print(char c) throws IOException {  
  141.         print(String.valueOf(c));  
  142.     }  
  143.   
  144.     /** 
  145.      * 
  146.      * Writes an int to the client, 
  147.      * with no carriage return-line feed (CRLF)  
  148.      * at the end. 
  149.      * 
  150.      * @param i         the int to send to the client 
  151.      * 
  152.      * @exception IOException   if an input or output exception occurred 
  153.      * 
  154.      */    
  155.   
  156.     public void print(int i) throws IOException {  
  157.         print(String.valueOf(i));  
  158.     }  
  159.   
  160.   
  161.   
  162.    
  163.     /** 
  164.      *  
  165.      * Writes a <code>long</code> value to the client, 
  166.      * with no carriage return-line feed (CRLF) at the end. 
  167.      * 
  168.      * @param l         the <code>long</code> value  
  169.      *              to send to the client 
  170.      * 
  171.      * @exception IOException   if an input or output exception  
  172.      *              occurred 
  173.      *  
  174.      */  
  175.   
  176.     public void print(long l) throws IOException {  
  177.         print(String.valueOf(l));  
  178.     }  
  179.   
  180.   
  181.   
  182.     /** 
  183.      * 
  184.      * Writes a <code>float</code> value to the client, 
  185.      * with no carriage return-line feed (CRLF) at the end. 
  186.      * 
  187.      * @param f         the <code>float</code> value 
  188.      *              to send to the client 
  189.      * 
  190.      * @exception IOException   if an input or output exception occurred 
  191.      * 
  192.      * 
  193.      */  
  194.   
  195.     public void print(float f) throws IOException {  
  196.         print(String.valueOf(f));  
  197.     }  
  198.   
  199.   
  200.   
  201.     /** 
  202.      * 
  203.      * Writes a <code>double</code> value to the client, 
  204.      * with no carriage return-line feed (CRLF) at the end. 
  205.      *  
  206.      * @param d         the <code>double</code> value 
  207.      *              to send to the client 
  208.      * 
  209.      * @exception IOException   if an input or output exception occurred 
  210.      * 
  211.      */  
  212.   
  213.     public void print(double d) throws IOException {  
  214.         print(String.valueOf(d));  
  215.     }  
  216.   
  217.   
  218.   
  219.     /** 
  220.      * Writes a carriage return-line feed (CRLF) 
  221.      * to the client. 
  222.      * 
  223.      * 
  224.      * 
  225.      * @exception IOException   if an input or output exception occurred 
  226.      * 
  227.      */  
  228.   
  229.     public void println() throws IOException {  
  230.         print(" ");  
  231.     }  
  232.   
  233.   
  234.   
  235.     /** 
  236.      * Writes a <code>String</code> to the client,  
  237.      * followed by a carriage return-line feed (CRLF). 
  238.      * 
  239.      * 
  240.      * @param s         the <code>String</code> to write to the client 
  241.      * 
  242.      * @exception IOException   if an input or output exception occurred 
  243.      * 
  244.      */  
  245.     public void println(String s){  
  246.         println(s, "UTF-8");  
  247.     }  
  248.     public void println(String s, String charsetName){  
  249.         /* 
  250.          * 解决中文乱码问题 
  251.          */  
  252.         try {  
  253.             print(s,charsetName);  
  254.             println();  
  255.         } catch (IOException e) {  
  256.             throw new RuntimeException(e);  
  257.         }  
  258.     }  
  259.   
  260.   
  261.   
  262.   
  263.     /** 
  264.      * 
  265.      * Writes a <code>boolean</code> value to the client,  
  266.      * followed by a  
  267.      * carriage return-line feed (CRLF). 
  268.      * 
  269.      * 
  270.      * @param b         the <code>boolean</code> value  
  271.      *              to write to the client 
  272.      * 
  273.      * @exception IOException   if an input or output exception occurred 
  274.      * 
  275.      */  
  276.   
  277.     public void println(boolean b) throws IOException {  
  278.         print(b);  
  279.         println();  
  280.     }  
  281.   
  282.   
  283.   
  284.     /** 
  285.      * 
  286.      * Writes a character to the client, followed by a carriage 
  287.      * return-line feed (CRLF). 
  288.      * 
  289.      * @param c         the character to write to the client 
  290.      * 
  291.      * @exception IOException   if an input or output exception occurred 
  292.      * 
  293.      */  
  294.   
  295.     public void println(char c) throws IOException {  
  296.         print(c);  
  297.         println();  
  298.     }  
  299.   
  300.   
  301.   
  302.     /** 
  303.      * 
  304.      * Writes an int to the client, followed by a  
  305.      * carriage return-line feed (CRLF) character. 
  306.      * 
  307.      * 
  308.      * @param i         the int to write to the client 
  309.      * 
  310.      * @exception IOException   if an input or output exception occurred 
  311.      * 
  312.      */  
  313.   
  314.     public void println(int i) throws IOException {  
  315.         print(i);  
  316.         println();  
  317.     }  
  318.   
  319.   
  320.   
  321.     /**   
  322.      * 
  323.      * Writes a <code>long</code> value to the client, followed by a  
  324.      * carriage return-line feed (CRLF). 
  325.      * 
  326.      * 
  327.      * @param l         the <code>long</code> value to write to the client 
  328.      * 
  329.      * @exception IOException   if an input or output exception occurred 
  330.      * 
  331.      */    
  332.   
  333.     public void println(long l) throws IOException {  
  334.         print(l);  
  335.         println();  
  336.     }  
  337.   
  338.   
  339.   
  340.     /** 
  341.      * 
  342.      * Writes a <code>float</code> value to the client,  
  343.      * followed by a carriage return-line feed (CRLF). 
  344.      * 
  345.      * @param f         the <code>float</code> value  
  346.      *              to write to the client 
  347.      * 
  348.      * 
  349.      * @exception IOException   if an input or output exception  
  350.      *              occurred 
  351.      * 
  352.      */  
  353.   
  354.     public void println(float f) throws IOException {  
  355.         print(f);  
  356.         println();  
  357.     }  
  358.   
  359.   
  360.   
  361.     /** 
  362.      * 
  363.      * Writes a <code>double</code> value to the client,  
  364.      * followed by a carriage return-line feed (CRLF). 
  365.      * 
  366.      * 
  367.      * @param d         the <code>double</code> value 
  368.      *              to write to the client 
  369.      * 
  370.      * @exception IOException   if an input or output exception occurred 
  371.      * 
  372.      */  
  373.   
  374.     public void println(double d) throws IOException {  
  375.         print(d);  
  376.         println();  
  377.     }  
  378.     /** 
  379.      * Flushes this output stream and forces any buffered output bytes  
  380.      * to be written out. The general contract of <code>flush</code> is  
  381.      * that calling it is an indication that, if any bytes previously  
  382.      * written have been buffered by the implementation of the output  
  383.      * stream, such bytes should immediately be written to their  
  384.      * intended destination. 
  385.      * <p> 
  386.      * If the intended destination of this stream is an abstraction provided by 
  387.      * the underlying operating system, for example a file, then flushing the 
  388.      * stream guarantees only that bytes previously written to the stream are 
  389.      * passed to the operating system for writing; it does not guarantee that 
  390.      * they are actually written to a physical device such as a disk drive. 
  391.      * <p> 
  392.      * The <code>flush</code> method of <code>OutputStream</code> does nothing. 
  393.      * 
  394.      * @exception  IOException  if an I/O error occurs. 
  395.      */  
  396.     public void flush() throws IOException {  
  397.         outputStream.flush();  
  398.     }  
  399.   
  400.     /** 
  401.      * Closes this output stream and releases any system resources  
  402.      * associated with this stream. The general contract of <code>close</code>  
  403.      * is that it closes the output stream. A closed stream cannot perform  
  404.      * output operations and cannot be reopened. 
  405.      * <p> 
  406.      * The <code>close</code> method of <code>OutputStream</code> does nothing. 
  407.      * 
  408.      * @exception  IOException  if an I/O error occurs. 
  409.      */  
  410.     public void close() throws IOException {  
  411.         outputStream.close();  
  412.     }  
  413.       
  414.     /** 
  415.      * Resets the <code>count</code> field of this byte array output  
  416.      * stream to zero, so that all currently accumulated output in the  
  417.      * output stream is discarded. The output stream can be used again,  
  418.      * reusing the already allocated buffer space.  
  419.      * 
  420.      * @see     java.io.ByteArrayInputStream#count 
  421.      */  
  422.     public void reset() {  
  423.         outputStream.reset();  
  424.     }  
  425.       
  426.     public byte[] toByteArray() {  
  427.         return outputStream.toByteArray();  
  428.     }  
  429. }  


在web.xml中配置 PageVisitFilter,当我们访问应用中以.htm,.html,.jsp,.js,.ajax,.css结尾的资源的使用,服务器端就开启http gzip压缩,将压缩后的信息通过http 协议传递给浏览器. 

[html] view plain copy
 
  1. <filter>  
  2.   <filter-name>Page Visit Filter</filter-name>  
  3.   <filter-class>com.tyyd.framework.web.PageVisitFilter</filter-class>   
  4.  </filter>  
  5.   
  6.  <filter-mapping>  
  7.   <filter-name>Page Visit Filter</filter-name>  
  8.   <url-pattern>/*</url-pattern>  
  9.  </filter-mapping>  

3、AJAX也可以通过这种方式压缩

只需知道ajax请求的后缀添加到下面的代码中即可:

//需要过滤的扩展名:.htm,.html,.jsp,.js,.ajax,.css

String gzippPattern=",.htm,.html,.jsp,.js,.ajax,.css,";

原文地址:https://www.cnblogs.com/myibm/p/7243426.html