JAva webはGzip圧縮伝送(回転)を実現

28019 ワード

Web上でのデータの転送量を削減し、転送時間を短縮し、ユーザー体験を増やすために、ブラウザの多くはGzip圧縮技術をサポートしています.httpのリクエストヘッダAccept-Encoding:gzip、deflateは今回のリクエストがGzip圧縮後のデータを受け入れることができることを示していますが、これはクライアントが受け取るデータが圧縮データであることを示しているだけで、サービス側は具体的にどのように圧縮を実現しますか?サービス側が圧縮を実現したデータ転送について、コード面から説明します.最初のステップでは、応答オブジェクトHttpServertResponseをパッケージ化して、HttpServertResponseWrapperのMyResponseオブジェクトを継承します.MyResponseクラスは親のgetWriter()メソッドを書き換えます.getWriter()メソッドでは、応答データをPrintWriterにキャッシュし、PrintWriterにキャッシュされたデータを取得する方法getBytes()を外部に提供します.第2部では、HttpServiceletResponseオブジェクトをパッケージングした後、フィルタGzipFilterを作成して圧縮する必要がある要求データをフィルタする必要があります.chain.doFilter()メソッドを実行する前に、HttpServiceletResponseを独自のMyResponseオブジェクトとしてパッケージングし、doFilter()メソッドを実行する必要があります.次に、最初にキャッシュした応答データを取得し、GZIPOutputStream圧縮を行い、圧縮したデータをクライアントに返します.第3部は、フィルタリングが必要な要求タイプ、すなわちフィルタパスを構成する.
具体的なコードは以下の通りである:一、包装応答対象HttpServiceletResponse
package com.qbian.gzip;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;

public class MyResponse extends HttpServletResponseWrapper{

    private ByteArrayOutputStream bytes = new ByteArrayOutputStream();
    private HttpServletResponse response;
    private PrintWriter pwrite;

    public MyResponse(HttpServletResponse response) {
        super(response);
        this.response = response;
    }

    @Override
    public ServletOutputStream getOutputStream() throws IOException {
        return new MyServletOutputStream(bytes); //       byte  
    }

    /**
     *       getWriter()   ,         PrintWriter  
     */
    @Override
    public PrintWriter getWriter() throws IOException {
        try{
            pwrite = new PrintWriter(new OutputStreamWriter(bytes, "utf-8"));
        } catch(UnsupportedEncodingException e) {
            e.printStackTrace();
        }

        return pwrite;
    }

    /**
     *       PrintWriter        
     * @return
     */
    public byte[] getBytes() {
        if(null != pwrite) {
            pwrite.close();
            return bytes.toByteArray();
        } 

        if(null != bytes) {
            try {
                bytes.flush();
            } catch(IOException e) {
                e.printStackTrace();
            }
        }

        return bytes.toByteArray();
    }

    class MyServletOutputStream extends ServletOutputStream {
        private ByteArrayOutputStream ostream ;

        public MyServletOutputStream(ByteArrayOutputStream ostream) {
            this.ostream = ostream;
        }

        @Override
        public void write(int b) throws IOException {
            ostream.write(b); //       stream  
        }

    }

}

二、フィルタGzipFilterの作成
package com.qbian.filter;

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

import com.qbian.gzip.MyResponse;

public class GzipFilter implements Filter{

    @Override
    public void destroy() {

    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse resp = (HttpServletResponse) response;
        MyResponse mResp = new MyResponse(resp); //        resp        

        chain.doFilter(req, mResp);

        byte[] bytes = mResp.getBytes(); //          
        System.out.println("     :" + bytes.length);

        ByteArrayOutputStream bout = new ByteArrayOutputStream();
        GZIPOutputStream gzipOut = new GZIPOutputStream(bout); //    GZIPOutputStream    

        gzipOut.write(bytes); //          Gzip     
        gzipOut.close(); //         bout      

        byte[] bts = bout.toByteArray();
        System.out.println("     :" + bts.length);

        resp.setHeader("Content-Encoding", "gzip"); //        
        resp.getOutputStream().write(bts); //            

    }

    @Override
    public void init(FilterConfig arg0) throws ServletException {
        System.out.println("+++    。");
    }

}

三、web.xmlで圧縮が必要なリクエストパスを構成する
  
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"  
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee   
    http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">  
    <display-name>demodisplay-name>

    
    <filter>
        <filter-name>gzipFfilter-name>
        <filter-class>com.qbian.filter.GzipFilterfilter-class>
    filter>
    
    <filter-mapping>
        <filter-name>gzipFfilter-name>
        <url-pattern>*.jsurl-pattern>
    filter-mapping>
    
    <filter-mapping>
        <filter-name>gzipFfilter-name>
        <url-pattern>*.htmlurl-pattern>
    filter-mapping>
    
    <filter-mapping>
        <filter-name>gzipFfilter-name>
        <url-pattern>*.cssurl-pattern>
    filter-mapping>

web-app>

最後に圧縮の効果を比較して、web.xmlの
<filter-mapping>
    <filter-name>gzipFfilter-name>
    <url-pattern>*.jsurl-pattern>
filter-mapping>

注記を削除し、サーバにJavaScriptファイルを要求します.具体的な情報は次の図に示します.
さらに、*.jsフィルタの構成についてコメントを解き、機能させます.次に、要求したJavaScriptファイルを要求し、サーバ応答のファイルサイズを見てみましょう.具体的な情報は下図のようになります.
バックグラウンド印刷の圧縮前後のサイズの比較を見てみましょう.下図に示します.
以上の比較情報から,我々が書いたGzip圧縮フィルタが機能し,圧縮率が高いことが分かる.これはサービス側の圧縮で、フロントエンドのJavaScriptとCSSもオンライン時に圧縮する必要がありますが、フロントエンド構築ツールが多いので、ここでは簡単に説明しません.まとめ:現在の開発はすべて前後端分離で、フロントエンドフレームワークも多く、私が今回使ったのはangularJsで、1つのページアプリケーションにとってngがロードするjsファイルはたくさんあります.ngのデフォルトロード方式は、起動後にangular.bootstrap()メソッドを実行し、作成した関連コントローラとそのサービス、すなわちデフォルトのロード方式が同期ロードされるので、JavaScriptファイルをマージ圧縮する必要があります.
原文:https://blog.csdn.net/qbian/article/details/53909778?utm_source=copy