關於靜態資源壓縮技術

  HTTP 壓縮能夠大大提升瀏覽網站的速度,它的原理是,在客戶端請求網頁後,從服務器端將網頁文件壓縮,再下載到客戶端,由客戶端的瀏覽器負責解壓縮並瀏覽。相對 於普通的瀏覽過程HTML ,CSS,Javascript , Text ,它能夠節省40%左右的流量。更爲重要的是,它能夠對動態生成的,包括CGI、PHP , JSP , ASP , Servlet,SHTML等輸出的網頁也能進行壓縮,壓縮效率驚人。
目前實現gzip壓縮有2種辦法:


方法1、是有的容器(服務器)提供的功能,但這個侷限於特定容器。好比 apache+tomcat 或者 resin-pro
方法2、是 部署前手動 gzip 壓縮,配合 servlet 過濾器使用,這個能實現 gzip 功能,可是下降了靈活性。


方案一
一、TOMCAT配置GZIP壓縮:

tomcat5.5.x配置
修改%TOMCAT_HOME%\conf \server.xml啓用支持gzip壓縮.
添加下列屬性
compression="on"
compressionMinSize="2048"
noCompressionUserAgents="gozilla, traviata"
compressableMimeType="text/html,text/xml"
TOMCAT配置說明
1) compression="on" 打開壓縮功能
2) compressionMinSize="2048" 啓用壓縮的輸出內容大小,這裏面默認爲2KB
3) noCompressionUserAgents="gozilla, traviata" 對於如下的瀏覽器,不啓用壓縮
4) compressableMimeType="text/html,text/xml" 壓縮類型

Resin容器中配置GZIP壓縮方法

http://localhost:8080/MyProj/pdf/0.jpg 能夠打開一張圖片。用Httpwatch查看
Accept-Encoding: gzip, deflate
Sent    :    315
Received    43106

開始配置Resin

我按照這樣的配置:
<web-app id="/" root-directory="webapps/MyProj">
<filter filter-name="gzip" filter-class="com.caucho.filters.GzipFilter">
<init>
<use-vary>true</use-vary>
</init>
</filter>
<filter-mapping filter-name="gzip">
<url-pattern>
<exclude-pattern>*.jpg</exclude-pattern>
<include-pattern>/*</include-pattern>
</url-pattern>
</filter-mapping>
</web-app>

再測試發現不起做用!不清楚如何配置哦!
我再看了一下資料上面有講說 須要resin的專業版即resin-pro
如今再看下個人resin :Resin-3.2.1 (built Fri, 17 Oct 2008 04:11:01 PDT)

果真是個人版本不一致致使的。從新從網上下載一下專業版的RESIN下來再試!
如下是我再測試的過程:
測試發現仍是不行呀!我昏~~~ 不過感受專業版與普通版在配置上面仍是有點差異的
待續未完!

方案二:
設置Content-Encoding

Content-Encoding 文檔的編碼(Encode)方法。只有在解碼以後才能夠獲得Content-Type頭指定的內容類型。利用gzip壓縮文檔可以顯著地減小HTML文檔 的下載時間。Java的GZIPOutputStream能夠很方便地進行gzip壓縮,但只有Unix上的Netscape和Windows上的IE 四、IE 5才支持它。所以,Servlet應該經過查看Accept-Encoding頭(即request.getHeader("Accept- Encoding"))檢查瀏覽器是否支持gzip,爲支持gzip的瀏覽器返回經gzip壓縮的HTML頁面,爲其餘瀏覽器返回普通頁面。
壓縮流
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException {
OutputStream out = null;
String encoding = request.getHeader("Accept-Encoding");  
if (encoding != null && encoding.indexOf("gzip") != -1){
request.setHeader("Content-Encoding" , "gzip");  
out = new GZIPOutputStream(request.getOutputStream());
} 
else if (encoding != null && encoding.indexOf("comdivss") != -1){
request.setHeader("Content-Encoding" , "comdivss");  
out = new ZIPOutputStream(request.getOutputStream());
}else{  
out = request.getOutputStream();



實例:
採用gzip servlet filter實現
從 HTTP/1.1 開始,客戶端就能夠在請求頭中添加
Accept-Encoding: gzip,deflate      (能夠從HTTP WATCH中查看發現確實支持)
來向請求的服務器代表本身支持 Gzip 壓縮的響應。Web 服務器則在響應頭中添加
Content-Encoding: gzip
來向客戶端代表響應體是通過 gzip 壓縮的。

程序代碼以下:
(在此很是感謝 http://tdcq.iteye.com/blog/453644 提供代碼)

具體代碼以下:
package sh.blog.util.web.filter;
import java.io.IOException;
import java.util.zip.GZIPOutputStream;
import javax.servlet.ServletOutputStream;
public class CompressedStream extends ServletOutputStream {
private ServletOutputStream out;
private GZIPOutputStream     gzip;
/**
* 指定壓縮緩衝流
* @param 輸出流到壓縮
* @throws IOException if an error occurs with the {@link GZIPOutputStream}.
*/
public CompressedStream(ServletOutputStream out) throws IOException {
this.out = out;
reset();
}

/** @see ServletOutputStream * */
public void close() throws IOException {
gzip.close();
}

/** @see ServletOutputStream * */
public void flush() throws IOException {
gzip.flush();
}

/** @see ServletOutputStream * */
public void write(byte[] b) throws IOException {
write(b, 0, b.length);
}

/** @see ServletOutputStream * */
public void write(byte[] b, int off, int len) throws IOException {
gzip.write(b, off, len);
}

/** @see ServletOutputStream * */
public void write(int b) throws IOException {
gzip.write(b);
}      

public void reset() throws IOException {
gzip = new GZIPOutputStream(out);
}

}



package sh.blog.util.web.filter;
import java.io.IOException;
import java.io.PrintWriter;   
import javax.servlet.ServletOutputStream;   
import javax.servlet.http.HttpServletResponse;   
import javax.servlet.http.HttpServletResponseWrapper;     

public class CompressionResponse extends HttpServletResponseWrapper{
protected HttpServletResponse response;   
private ServletOutputStream out;   
private CompressedStream compressedOut;  
private PrintWriter writer;   
protected int contentLength;   

public CompressionResponse(HttpServletResponse response) throws IOException {   
super(response);
this.response = response;   
compressedOut = new CompressedStream(response.getOutputStream());
}

public void setContentLength(int len) {
contentLength = len;   
}

public ServletOutputStream getOutputStream() throws IOException {   
if (null == out) {   
if (null != writer) {  
throw new IllegalStateException("getWriter() has already been called on this response.");   
}
out = compressedOut;   
}
return out;
}

public PrintWriter getWriter() throws IOException {   
if (null == writer) {   
if (null != out) {   
throw new IllegalStateException("getOutputStream() has already been called on this response.");
}
writer = new PrintWriter(compressedOut);  
}
return writer;   

}

public void flushBuffer() {   
try {   
if (writer != null) {
writer.flush();
}else if (out != null) {  
out.flush();   
}

}catch (IOException e) {  
e.printStackTrace();   
}
}

public void reset() {
super.reset();   
try {   
compressedOut.reset();   
}catch (IOException e) {  
throw new RuntimeException(e);   
}
}

public void resetBuffer() {   
super.resetBuffer();   
try {   
compressedOut.reset();   
}catch (IOException e) {  
throw new RuntimeException(e);
}
}

public void close() throws IOException {   
compressedOut.close();   
}



}



package sh.blog.util.web.filter;

import java.io.IOException;   
import java.util.Enumeration;   
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 org.apache.commons.logging.Log;   
import org.apache.commons.logging.LogFactory;   

public class CompressionFilter implements Filter {   
protected Log log = LogFactory.getFactory().getInstance(this.getClass().getName());   

@SuppressWarnings("unchecked")   
public void doFilter(ServletRequest request, ServletResponse response,   
FilterChain chain) throws IOException, ServletException {   
boolean compress = false;   
if (request instanceof HttpServletRequest){   
HttpServletRequest httpRequest = (HttpServletRequest) request;  
Enumeration headers = httpRequest.getHeaders("Accept-Encoding");   
while (headers.hasMoreElements()){   
String value = (String) headers.nextElement();   
if (value.indexOf("gzip") != -1){   
compress = true;   
}   
}   
}   

if (compress){//若是瀏覽器支持則壓縮   
HttpServletResponse httpResponse = (HttpServletResponse) response;
httpResponse.addHeader("Content-Encoding", "gzip");   
CompressionResponse compressionResponse= new CompressionResponse(httpResponse);   
chain.doFilter(request, compressionResponse);   
compressionResponse.close();   
}   
else{//若是瀏覽器不支持則不壓縮   
chain.doFilter(request, response);   
}   

}   

public void init(FilterConfig config) throws ServletException {   

}   

public void destroy(){   
}   

}   
一共有三個CLASS文件!實現GZIP壓縮輸出響應

2.1 對圖片輸出作壓縮處理測試
創建目錄pdf裏面存儲圖片
第一步:不配置過濾器用HTTP WATCHE發現
image/jpeg : 42891 bytes, 670 x 446 pixels


第二步:配置Web.xml配置過濾器
<filter>
<filter-name>gzip</filter-name>
<filter-class>sh.blog.util.web.filter.CompressionFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>gzip</filter-name>
<url-pattern>/pdf/*</url-pattern>
</filter-mapping>

再用HTTP WATCH查看發現
image/jpeg : 42891 bytes, gzip compressed to 42712 bytes ( 0.417 % saving ), 670 x 446 pixels
實現了一次壓縮處理輸出!
PS:我再用png格式的圖片作過一次測試發現一次能夠實現GZIP壓縮輸出
結論:經過上面的過濾器可以實現對圖片的壓縮處理,提升響應速度!


2.2 對音樂的壓縮處理以MP3的輸出 爲測試對象

創建目錄music裏面存儲音樂
第一步:不配置過濾器發現
audio/mpeg : 9001 bytes of binary data

第二步:配置過濾器

<filter>
<filter-name>gzip</filter-name>
<filter-class>sh.blog.util.web.filter.CompressionFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>gzip</filter-name>
<url-pattern>/music/*</url-pattern>   
</filter-mapping>

再次查看發現:
audio/mpeg : , gzip compressed to 0 bytes ( 0 % saving )
結論:上面的算法對音樂文件不起壓縮做用。感受這種GZIP的算法應該是不一樣的格式算法不同


2.3 對JS文件壓縮輸出

第一步:不作壓縮
4864

第二步:配置壓縮
<filter>
<filter-name>gzip</filter-name>
<filter-class>sh.blog.util.web.filter.CompressionFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>gzip</filter-name>
<url-pattern>/scripts/*.js</url-pattern>   
</filter-mapping>

輸出:
application/x-javascript : 4636 bytes, gzip compressed to 69 bytes ( 98.5 % saving )

查看發現JS的壓縮是至關高的了!
結論:將JS存入指定的目錄而後直接對此目錄作GZIP壓縮輸出。能夠看到效果是顯著的!
經過作GZIP壓縮輸出以後能夠減小網絡帶寬流量從而加快下載速度!



2.4 對CSS文件壓縮輸出

第一步:沒有壓縮輸出
text/css : 413 bytes

第二步:壓縮

配置:
<filter>
<filter-name>gzip</filter-name>
<filter-class>sh.blog.util.web.filter.CompressionFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>gzip</filter-name>
<url-pattern>/scripts/*.js</url-pattern>   
<url-pattern>/style/*.css</url-pattern>
</filter-mapping>
結果:
text/css : 413 bytes, gzip compressed to 101 bytes ( 75.5 % saving )
結論:對CSS的壓縮效果也是很是明顯的哦!

2.5 對HTML頁面壓縮輸出

第一步:不壓縮
text/html : 2272 bytes

第二步;壓縮
<filter>
<filter-name>gzip</filter-name>
<filter-class>sh.blog.util.web.filter.CompressionFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>gzip</filter-name>
<url-pattern>/scripts/*.js</url-pattern>   
<url-pattern>/style/*.css</url-pattern>
<url-pattern>*.html</url-pattern>
</filter-mapping>
結果:
text/html : 2272 bytes, gzip compressed to 240 bytes ( 89.4 % saving )

結論:對HTML的壓縮效果也是很是明顯的哦!

2.6 對JSP頁面的壓縮
第一步:未作壓縮
text/html; charset=iso-8859-1 : 1008 bytes

第二步:壓縮輸出
<filter>
<filter-name>gzip</filter-name>
<filter-class>sh.blog.util.web.filter.CompressionFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>gzip</filter-name>
<url-pattern>/scripts/*.js</url-pattern>   
<url-pattern>/style/*.css</url-pattern>
<url-pattern>*.html</url-pattern>
<url-pattern>*.jsp</url-pattern>
</filter-mapping>

結果:頁面 無輸出!

結論:
以上的算法能夠應用於 圖片、HTML、CSS、JS的GZIP壓縮輸出。對於JSP頁面無效!

應用:

未來能夠在站點中編寫此類過濾器,將頁面內容儘量地作GZIP輸出提升下載的速度 javascript




這是我在別處看到帖子 比較不錯  但願你們能夠看下
css

相關文章
相關標籤/搜索