1. 程式人生 > >客戶端(android/ios)與java服務端tomcat的gzip實現

客戶端(android/ios)與java服務端tomcat的gzip實現

開始之前我們先來簡單說說gzip是幹什麼用的,為什麼要用

我們來舉個栗子
同一個請求他們使用gzip和不使用是完全兩個結果
例子一:正常未通過gzip壓縮的返回資料大小是100kb
例子二:添加了gzip壓縮的資料的返回資料大小可能只有40-20kb甚至10kb
怎樣,各位童鞋應該瞭解到這個gizp的作用了吧,沒錯,就是資料壓縮。

服務端配置gzip壓縮

服務端進行gzip的壓縮和解壓基本沒什麼難度,配置tomcat伺服器即可
server.xml進行修改

<Connector connectionTimeout="20000" 
    compression="on"
compressionMinSize="50" noCompressionUserAgents="gozilla, traviata" compressableMimeType="application/json" port="8080" protocol="HTTP/1.1" redirectPort="8443"/>

compression開啟壓縮
compressionMinSize最低壓縮大小,意思達到多少kb會開啟壓縮,預設是2048,即2kb
noCompressionUserAgents以下哪些瀏覽器不啟用壓縮
compressableMimeType

壓縮的資料型別

至於對html/css/js等等相關壓縮可以在compressableMimeType中補充,本文因為是對介面方面的壓縮所以不再描述

有同學問,我既然壓縮了,那就應該有解壓啊!

對,沒錯,童鞋你的問題真多。如果你的客戶端是android/ios的話確實需要自己解壓,但是如果你的客戶端是瀏覽器的話,那麼,你就不用管了,因為瀏覽器會幫你做這些工作,前提是你的html版本是html1.1+(我相信現在也找不到低於這個標準的吧?)

客戶端(android/ios)傳送和解壓gizp資料

客戶端方面其實也沒什麼,就是需要在傳送請求的時候告訴伺服器,我是支援gzip壓縮資料的,請你把資料壓一壓再給我,怎麼給?
通過標頭檔案註冊

Accept-Encoding: gzip, deflate

伺服器會檢測你的請求是否可以使用gzip格式,如果註冊了這個標頭檔案,那麼伺服器自動就會進行gzip的資料壓縮返回給客戶端

在返回的資料結果集中response的標頭檔案會有這麼一個屬性

Content-Encoding: gzip

然後客戶端只需要捕抓response中的標頭檔案是否包含這個屬性,如果包含了則需要對原始資料進行解壓,解壓出來的就是原始資料了,具體解壓程式碼這裡給出java方面的,其他客戶端可自行搜尋

GZIP解壓程式碼

package com.sspendi.framework.utils;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;

/**
 * Gzip 壓縮字串
 */
public class GZIP {
    /**
     * 字串的壓縮
     *
     * @param str 待壓縮的字串
     * @return 返回壓縮後的字串
     * @throws IOException
     */
    public static String compress(String str) throws IOException {
        if (null == str || str.length() <= 0) {
            return str;
        }
        // 建立一個新的輸出流
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        // 使用預設緩衝區大小建立新的輸出流
        GZIPOutputStream gzip = new GZIPOutputStream(out);
        // 將位元組寫入此輸出流
        gzip.write(str.getBytes("utf-8"));  //因為後臺預設字符集有可能是GBK字符集,所以此處需指定一個字符集
        gzip.close();
        // 使用指定的 charsetName,通過解碼位元組將緩衝區內容轉換為字串
        return out.toString("ISO-8859-1");
    }

    /**
     * 字串的解壓
     *
     * @param str 對字串解壓
     * @return 返回解壓縮後的字串
     * @throws IOException
     */
    public static String unCompress(String str) throws IOException {
        if (null == str || str.length() <= 0) {
            return str;
        }
        return unCompress(str.getBytes("ISO-8859-1"));
    }

    public static String unCompress(byte[] bs) throws IOException {
        // 建立一個新的輸出流
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        ByteArrayInputStream in = new ByteArrayInputStream(bs);
        // 使用預設緩衝區大小建立新的輸入流
        GZIPInputStream gzip = new GZIPInputStream(in);
        byte[] buffer = new byte[256];
        int n = 0;

        // 將未壓縮資料讀入位元組陣列
        while ((n = gzip.read(buffer)) >= 0) {
            out.write(buffer, 0, n);
        }
        // 使用指定的 charsetName,通過解碼位元組將緩衝區內容轉換為字串
        return out.toString("utf-8");
    }
}

至此,完成客戶端與服務端的gzip通訊,大大減少了流量。