zoukankan      html  css  js  c++  java
  • 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,";

  • 相关阅读:
    LeftoverDataException,依赖包,apache license 2.0
    GPL,BSD,Apache,MIT开源许可协议
    一次重构经历
    转载:reactor模式学习
    版本控制学习
    系统开发,出错处理,日志
    最近学习linux命令的一个总结
    sudo,linux 新建账号,并开通ssh登录
    运行R 报错R cannot R_TempDir, 继而发现/dev/mapper/VG00-LV01 磁盘空间已满
    用InputStream读出来转换成String类型
  • 原文地址:https://www.cnblogs.com/myibm/p/7243426.html
Copyright © 2011-2022 走看看