1. 程式人生 > >HTML壓縮(JSP的GZIP實現)

HTML壓縮(JSP的GZIP實現)

為其他瀏覽器返回普通頁面。

壓縮流
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.javaeye.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頁面無效!

應用: