WEB效能優化(一):Resin下的 GZIP壓縮
最近在做前端的效能優化,發現一個頁面引入的js、css等外部資源過多的話,瀏覽器第一次請求的時候會下載很大的資源,那麼在使用者網路不好的情況下,頁面的載入速度會受很大的影響,因此要對WEB前端做各種優化。
在此第一步做的就是所有資源的壓縮,在開發環境編寫好的js和css檔案,可以使用工具批量壓縮成min的檔案格式,那樣會壓縮一部分大小,但是js壓縮成min.js要注意有些方法可能不好使,這方面大家可以百度一下資料。
其次可以做本文所說的gzip壓縮,這種壓縮比率可以讓傳輸資原始檔的大小縮小為40%左右,也就是壓縮了60%多,這種效果也是很明顯的。
但是在調查過程中發現,網上全部都是基於tomcat或者ngix的配置檔案的修改,我一直沒有找到基於resin4的配置修改方式,因為就只能在程式碼上下功夫了。
原理就是做filter過濾,把返回給瀏覽器的資料全部做gzip壓縮,到時候瀏覽器會自動解壓的。程式碼裡的gzip壓縮其實就是java類中的一種壓縮方式而已,下面就上所用到的程式碼。
web.xml檔案,增加一個filter
工程裡面需要三個類
GzioFilter.java
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 GzioFilter implements Filter{
public void destroy() {
}
public void doFilter(ServletRequest req, ServletResponse res,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest request =(HttpServletRequest)req;
HttpServletResponse response =(HttpServletResponse)res;
String acceptEncoding = request.getHeader("Accept-Encoding");
if (acceptEncoding != null
&& acceptEncoding.toLowerCase().indexOf("gzip") != -1) {
GZipResponseWrapper gzipResponse = new GZipResponseWrapper(response);
chain.doFilter(request, gzipResponse);
gzipResponse.finishResponse();
}else{
chain.doFilter(request, response);
}
}
public void init(FilterConfig arg0) throws ServletException {
}
}
GZipOutputStream.java
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.zip.GZIPOutputStream;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
public class GZipOutputStream extends ServletOutputStream {
private HttpServletResponse response;
private GZIPOutputStream gzipOutputStream;
private ByteArrayOutputStream byteArrayOutputStream;
public GZipOutputStream(HttpServletResponse response) throws IOException {
this.response = response;
byteArrayOutputStream = new ByteArrayOutputStream();
gzipOutputStream = new GZIPOutputStream(byteArrayOutputStream);
}
public void write(int b) throws IOException {
gzipOutputStream.write(b);
}
public void close() throws IOException {
gzipOutputStream.finish();
byte[] content = byteArrayOutputStream.toByteArray();
response.addHeader("Content-Encoding", "gzip");
response.addHeader("Content-Length", Integer.toString(content.length));
ServletOutputStream out = response.getOutputStream();
out.write(content);
out.close();
}
public void flush() throws IOException {
gzipOutputStream.flush();
}
public void write(byte[] b, int off, int len) throws IOException {
gzipOutputStream.write(b, off, len);
}
public void write(byte[] b) throws IOException {
gzipOutputStream.write(b);
}
}
GZipResponseWrapper.java
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 response;
private GZipOutputStream gzipOutputStream;
private PrintWriter writer;
public GZipResponseWrapper(HttpServletResponse response) throws IOException {
super(response);
this.response = response;
}
public ServletOutputStream getOutputStream() throws IOException {
if (gzipOutputStream == null)
gzipOutputStream = new GZipOutputStream(response);
return gzipOutputStream;
}
public PrintWriter getWriter() throws IOException {
if (writer == null)
writer = new PrintWriter(new OutputStreamWriter(
new GZipOutputStream(response), "UTF-8"));
return writer;
}
public void setContentLength(int contentLength) {
}
public void flushBuffer() throws IOException {
gzipOutputStream.flush();
}
public void finishResponse() throws IOException {
if (gzipOutputStream != null)
gzipOutputStream.close();
if (writer != null)
writer.close();
}
}
原理很簡單,做web開發的同學應該都可以看懂。