您的位置:首页 > 运维架构 > 网站架构

Gzip压缩优化网站

2016-06-07 12:24 357 查看
网站常使用GZIP压缩算法对网页内容进行压缩,然后传给浏览器,以减小数据传输量,提高响应速度。浏览器接收到GZIP压缩数据后会自动解压并正确显示。GZIP加速常用于解决网速慢的瓶颈。

压缩Filter中需要先判断客户浏览器时候支持GZip自动解压,如果支持,则进行GZIP压缩,否则不压缩。判断的依据是浏览器提供的Header信息,代码如下:

GZipFilter.java

​package com.rom.util;

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;

/**
* Servlet Filter implementation class GzipFilter
*/
public class GzipFilter implements Filter {

/**
* Default constructor.
*/
public GzipFilter() {
// TODO Auto-generated constructor stub
}

/**
* @see Filter#destroy()
*/
public void destroy() {
// TODO Auto-generated method stub
}

/**
* @see Filter#doFilter(ServletRequest, ServletResponse, FilterChain)
*/
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) {
// TODO Auto-generated method stub
// place your code here

System.out.println("压缩的");

// TODO Auto-generated method stub
HttpServletRequest request = (HttpServletRequest)req;
HttpServletResponse response =(HttpServletResponse)res;

String acceptEncoding =request.getHeader("Accept-Encoding");
//支持的编码方式

try {
if(acceptEncoding != null && acceptEncoding.toLowerCase().indexOf("gzip") != -1){

System.out.println("执行压缩的方法");

//如果客户浏览器支持GZIP格式,则使用GZIP压缩数据
GZipResponseWrapper gzipRes = new GZipResponseWrapper(response);

chain.doFilter(request, gzipRes);//doFilter,使用自定义的response
gzipRes.finishResponse();//输出压缩数据

}else{
System.out.println("没有压缩");

chain.doFilter(request, response);//否则不压缩
}
//          chain.doFilter(request, response);
} catch (IOException e) {
e.printStackTrace();
} catch (ServletException e) {
e.printStackTrace();
}
}

/**
* @see Filter#init(FilterConfig)
*/
public void init(FilterConfig fConfig) throws ServletException {
// TODO Auto-generated method stub
}

}


GZipResponseWrapper为自定义的response类,内部将对输出的内容进行GZIP压缩。它集成HttpServletResponseWrapper类,也是一个“伪装”的response,不真正输出内容到客户端。

GZipResponseWrapper.java

package com.rom.util;

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 {
// 默认的 response
private HttpServletResponse response;

// 自定义的 outputStream, 执行close()的时候对数据压缩,并输出
private GZipOutputStream gzipOutputStream;

// 自定义 printWriter,将内容输出到 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();
}
}


getWriter()与getOutputStream()都使用了GZipOutputStream类。这是自定义的一个ServletOutputStream类,它先将数据缓存起来,然后使用JDK自带的GZIP压缩类将数据压缩,并输出到客户端浏览器。GZIP数据压缩与输出都在该类里实现的。

GZipOutputStream.java

package com.rom.util;

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);
}

}


添加xml配置文件

<filter>
<display-name>GzipFilter</display-name>
<filter-name>GzipFilter</filter-name>
<filter-class>com.rom.util.GzipFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>GzipFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: