客戶端(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通訊,大大減少了流量。