使用gzip優化web應用(filter實現)

gzip是http協議中使用的一種加密算法,客戶端向web服務器端發出了請求後,通常情況下服務器端會將頁面文件和其他資源,返回到客戶端,客戶端加載後渲染呈現,這種情況文件一般都比較大,如果開啓Gzip ,那麼服務器端響應後,會將頁面,JS,CSS等文本文件或者其他文件通過高壓縮算法將其壓縮,然後傳輸到客戶端,由客戶端的瀏覽器負責解壓縮與呈現。通常能節省40%以上的流量(一般都有60%左右),一些PHP,JSP文件也能夠進行壓縮。

實      現:  

Tomcat 開啓Gzip :

1.找到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"

將它改成如下的形式(其實在上面代碼的下面已經有了,將他們打開而已。):

<!-- Define a non-SSL HTTP/1.1 Connector on port 8080 --> <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" >

你甚至可以壓縮圖片:

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

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

開啓後重啓Tomcat ,通過瀏覽器查看headers信息就能看到是否開啓(firebug中有),如果開啓了,那麼transfer-encoding就會是Gzip,否則就是chunked。

 

在代碼級別完成web應用的gzip壓縮的開啓:

 

1.Wrapper  用來包裝HttpServletResponse 對象 

Java代碼 

package com.shop.gzip;

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;

public class Wrapper extends HttpServletResponseWrapper {
    public static final int OT_NONE = 0, OT_WRITER = 1, OT_STREAM = 2;
    private int outputType = OT_NONE;
    private ServletOutputStream output = null;
    private PrintWriter writer = null;
    private ByteArrayOutputStream buffer = null;

    public Wrapper(HttpServletResponse resp) throws IOException {
        super(resp);
        buffer = new ByteArrayOutputStream();
    }

    public PrintWriter getWriter() throws IOException {
        if (outputType == OT_STREAM)
            throw new IllegalStateException();
        else if (outputType == OT_WRITER)
            return writer;
        else {
            outputType = OT_WRITER;
            writer = new PrintWriter(new OutputStreamWriter(buffer,
                    getCharacterEncoding()));
            return writer;
        }
    }

    public ServletOutputStream getOutputStream() throws IOException {
        if (outputType == OT_WRITER)
            throw new IllegalStateException();
        else if (outputType == OT_STREAM)
            return output;
        else {
            outputType = OT_STREAM;
            output = new WrappedOutputStream(buffer);
            return output;
        }
    }

    public void flushBuffer() throws IOException {
        if (outputType == OT_WRITER)
            writer.flush();
        if (outputType == OT_STREAM)
            output.flush();
    }

    public void reset() {
        outputType = OT_NONE;
        buffer.reset();
    }

    public byte[] getResponseData() throws IOException {
        flushBuffer();
        return buffer.toByteArray();

    }

    class WrappedOutputStream extends ServletOutputStream {
        private ByteArrayOutputStream buffer;

        public WrappedOutputStream(ByteArrayOutputStream buffer) {
            this.buffer = buffer;
        }

        public void write(int b) throws IOException {
            buffer.write(b);
        }

        public byte[] toByteArray() {
            return buffer.toByteArray();
        }
    }

 

 

2.過濾器

 

Java代碼 

 

 package com.shop.gzip;

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.ServletOutputStream;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class GZipFilter implements Filter {

    public void destroy() {
    }
      /**
       * 判斷瀏覽器是否支持GZIP
       * @param request
       * @return
       */
      private static boolean isGZipEncoding(HttpServletRequest request){
        boolean flag=false;
        String encoding=request.getHeader("Accept-Encoding");
        if(encoding.indexOf("gzip")!=-1){
          flag=true;
        }
        return flag;
      }
      
    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException {
        HttpServletResponse resp = (HttpServletResponse) response;
        HttpServletRequest req=(HttpServletRequest)request;
        if(isGZipEncoding(req)){
            Wrapper wrapper = new Wrapper(resp);
            chain.doFilter(request, wrapper);
            byte[] gzipData = gzip(wrapper.getResponseData());
            resp.addHeader("Content-Encoding", "gzip");
            resp.setContentLength(gzipData.length);
            ServletOutputStream output = response.getOutputStream();
            output.write(gzipData);
            output.flush();
        } else {
            chain.doFilter(request, response);
        }        

    }

    public void init(FilterConfig arg0) throws ServletException {

    }

    private byte[] gzip(byte[] data) {
        ByteArrayOutputStream byteOutput = new ByteArrayOutputStream(10240);
        GZIPOutputStream output = null;
        try {
            output = new GZIPOutputStream(byteOutput);
            output.write(data);
        } catch (IOException e) {
        } finally {
            try {
                output.close();
            } catch (IOException e) {
            }
        }
        return byteOutput.toByteArray();
    }

}

3.在web.xml中配置 GZipFilter,當我們訪問應用中以.do結尾的資源的使用,服務器端就開啓http gzip壓縮,將壓縮後的信息通過http 協議傳遞給瀏覽器.  

  

Xml代碼 

<filter>  

  <filter-name>ecsideExport</filter-name>  

  <filter-class>com.web.servlet.GZipFilter</filter-class>  

 </filter>  

<filter-mapping>  

             <filter-name>ecsideExport</filter-name>  

            <url-pattern>*.do</url-pattern>  

</filter-mapping>   

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章