HTML壓縮(JSP的GZIP實現)
阿新 • • 發佈:2018-12-31
為其他瀏覽器返回普通頁面。
壓縮流
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頁面無效!
應用:
壓縮流
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頁面無效!
應用: