過濾器實現檔案的gzip壓縮
gzip和介紹和回想方式,可以參考我的這篇部落格 gzip的介紹以及web伺服器對檔案壓縮的支援。本文介紹如何藉助j2ee的過濾器Filter自己實現gzip對網頁檔案的壓縮。
將該過濾器配置在web.xml中的第一個,實現對*.js檔案攔截
package net.aty;
import java.io.IOException;
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;
public class GZIPFilter implements Filter
{
@Override
public void destroy()
{
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException,
ServletException
{
HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpServletResponse httpResponse = (HttpServletResponse) response;
String ac = httpRequest.getHeader("accept-encoding");
// 檢查瀏覽器是否支援gzip格式
if (ac != null && ac.contains("gzip"))
{
httpResponse.setHeader("Content-Encoding", "gzip");
//對原始的response進行封裝
GZIPResponseWrapper wrappedResponse = new GZIPResponseWrapper(httpResponse);
chain.doFilter(httpRequest, wrappedResponse);
// 完成gzip壓縮,將壓縮後的資料寫入web伺服器建立的原始輸出流中
// 一定要手動關閉wrappedResponse,否則httpResponse中資料是空,伺服器不能正確的將資料傳給瀏覽器
wrappedResponse.finishCompress();
}
else
{
chain.doFilter(request, httpResponse);
}
}
@Override
public void init(FilterConfig config) throws ServletException
{
}
}
package net.aty;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
public class GZIPResponseWrapper extends HttpServletResponseWrapper
{
private HttpServletResponse origResponse = null;
private GZIPResponseStream stream = null;
private PrintWriter writer = null;
public GZIPResponseWrapper(HttpServletResponse response) throws IOException
{
super(response);
this.origResponse = response;
}
public ServletOutputStream getOutputStream() throws IOException
{
if (this.writer != null)
{
throw new IllegalStateException("getWriter() has already been called!");
}
if (this.stream == null)
{
this.stream = this.createOutputStream();
}
return this.stream;
}
public PrintWriter getWriter() throws IOException
{
if (this.writer != null)
{
return this.writer;
}
if (this.stream != null)
{
throw new IllegalStateException("getOutputStream() has already been called!");
}
this.stream = this.createOutputStream();
this.writer = new PrintWriter(new OutputStreamWriter(this.stream, "UTF-8"));
return this.writer;
}
public void finishCompress() throws IOException
{
if (this.writer != null)
{
this.writer.close();
}
else if (this.stream != null)
{
this.stream.close();
}
}
public long getContentBytes()
{
return stream.getWriteBytes();
}
private GZIPResponseStream createOutputStream() throws IOException
{
return new GZIPResponseStream(origResponse.getOutputStream());
}
}
GZIPResponseStream 實現對GZIP的封裝
package net.aty;
import java.io.IOException;
import java.util.zip.GZIPOutputStream;
import javax.servlet.ServletOutputStream;
// 封裝web伺服器原始的httpResponse.getOutputStream().伺服器會將原本應該寫入httpResponse.getOutputStream()
// 中資料,寫入到GZIPOutputStream實現資料壓縮
public class GZIPResponseStream extends ServletOutputStream
{
private long writeBytes = 0;
private GZIPOutputStream gzipStream = null;
// outputStream是輸出目的地。如果在構建gzipStream之前,已經有資料寫入outputStream,那麼這些資料不會壓縮
public GZIPResponseStream(ServletOutputStream outputStream) throws IOException
{
this.gzipStream = new GZIPOutputStream(outputStream);
}
@Override
public void write(int asciiValue) throws IOException
{
this.gzipStream.write((byte) asciiValue);
writeBytes++;
}
@Override
public void write(byte bytesArray[]) throws IOException
{
this.write(bytesArray, 0, bytesArray.length);
}
@Override
public void write(byte bytesArray[], int offset, int length) throws IOException
{
this.gzipStream.write(bytesArray, offset, length);
writeBytes += length;
}
@Override
public void flush() throws IOException
{
this.gzipStream.flush();
}
@Override
public void close() throws IOException
{
this.gzipStream.finish();
this.gzipStream.flush();
this.gzipStream.close();
}
public long getWriteBytes()
{
return writeBytes;
}
}
自己通過除錯,得出以下幾個結論
1、response物件由web伺服器建立,當第一個filter拿到response的時候,內容是空的,這個時候還沒有誰向response響應流中寫入資料。
當走完最後個filter或servlet的時候,伺服器會將靜態的html或者動態的jsp寫入的reponse的響應流中。
2、GZIPFilter應該放在web.xml中作為第一個過濾器,這樣才可以保證所有寫入到response中的資料都經過gzip壓縮。
相關文章
- 使用gzip壓縮檔案
- Java實現檔案壓縮與解壓[zip格式,gzip格式]Java
- Vue開啟gzip壓縮檔案Vue
- 使用filter實現網站的gzip壓縮Filter網站
- 批處理 壓縮zip 並過濾部分檔案
- gzip的介紹以及web伺服器對檔案壓縮的支援Web伺服器
- 分析核心對gzip壓縮檔案進行解壓的方法(轉)
- C#實現通過Gzip來對資料進行壓縮和解壓C#
- 過濾器應用【編碼、敏感詞、壓縮、轉義過濾器】過濾器
- 修復損壞的gzip壓縮檔案之原理篇
- java中listFiles(Filefilter filter)檔案過濾器的實現過程JavaFilter過濾器
- 關於Java的GZIP壓縮與.net C#的GZIP壓縮的差異JavaC#
- 哈夫曼實現檔案壓縮解壓縮(c語言)C語言
- 用 Huffman 樹實現檔案壓縮並解壓
- 關gzip壓縮,我有新發現
- 如何透過ZBlogPHP啟用Gzip壓縮?PHP
- 檔案壓縮和解壓縮
- Apache 開啟gzip壓縮Apache
- aix 檔案的壓縮與解壓縮AI
- java實現zip壓縮檔案/資料夾Java
- 圖解gzip壓縮檔案底層結構及檔案損壞的修復方法圖解
- 伺服器端如何開啟GZIP壓縮功能伺服器
- Node.js伺服器啟用Gzip壓縮Node.js伺服器
- javaWeb不生成臨時檔案實現壓縮檔案下載JavaWeb
- Linux中檔案的壓縮和解壓縮Linux
- linux下的檔案的壓縮和解壓縮Linux
- Java實現解壓縮檔案和資料夾Java
- Java實現多檔案邊壓縮邊下載Java
- linux下gzip的壓縮詳解Linux
- 給Tomcat,Apache配置gzip壓縮(HTTP壓縮)功能 (轉)TomcatApacheHTTP
- 用C#實現RAR檔案的自動解壓縮C#
- .NET 壓縮/解壓檔案
- gulp壓縮檔案
- Java檔案壓縮Java
- java 檔案壓縮Java
- vue-cli npm run build空白頁的兩個坑 webpack gzip檔案壓縮優化打包檔案VueNPMUIWeb優化
- Apache開啟GZIP壓縮功能方法Apache
- vue-cli3.0配置GZIP壓縮Vue