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

使用filter实现网站的gzip压缩

2017-03-23 14:42 295 查看

使用filter实现网站的gzip压缩

gzip可以提高网站的访问速度,所以还是有必要开启的,这里说说如何用filter实现

直接上代码

package com.educate.web.filter;

import com.educate.web.interceptor.LoginInterceptor;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.util.zip.GZIPOutputStream;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;

public class GzipFilter implements Filter {

private static final Logger LOGGER = LoggerFactory.getLogger(GzipFilter.class);

@Override
public void init(FilterConfig filterConfig) throws ServletException {
}

@Override
public void doFilter(ServletRequest req, ServletResponse res,
FilterChain chain) throws IOException, ServletException {

HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
if (isGZipEncoding(request)) {

//需要过滤的扩展名:.htm,.html,.jsp,.js,.ajax,.css,.ftl,.txt, 一般这些已经足够了,不建议压缩图片(具体百度)
String gzipPattern = ",.htm,.html,.jsp,.js,.ajax,.css,.ftl,.txt,";
String uri = request.getRequestURI();
//得到资源的后缀
String ext = FilenameUtils.getExtension(uri);

if (StringUtils.indexOf(gzipPattern, ",." + ext + ",") != -1) {

MyResponse resp = new MyResponse(response);
chain.doFilter(request, resp);// 放行--让后台去写

// 从增强版的resp的baout中(存放的是源字节数据),把数据取出来进行压缩,
// 然后再压缩后的数据用原生的response输出到客户端
ByteArrayOutputStream baout = resp.getBaout();
byte bs[] = baout.toByteArray();// 源字节数据
//太小的不压缩
if (bs.length > 512) {

LOGGER.debug("过滤的资源路径:" + uri);
LOGGER.debug("压缩前大小:" + bs.length);

ByteArrayOutputStream baout2 = new ByteArrayOutputStream();
GZIPOutputStream gout = new GZIPOutputStream(baout2);
gout.write(bs);// 把数据压缩到baout中
gout.close();

bs = baout2.toByteArray();
LOGGER.debug("压缩后大小:" + bs.length);

// 输出之前告诉客户端:我们的数据是gzip格式,然后输出
response.setHeader("Content-Encoding", "gzip");
response.setContentLength(bs.length);
}

ServletOutputStream output = response.getOutputStream();
output.write(bs);
output.flush();
} else {
chain.doFilter(request, response);
}
return;
} else {
chain.doFilter(request, response);
}

}

/**
* 判断浏览器是否支持GZIP
*
* @param request
* @return
*/
private boolean isGZipEncoding(HttpServletRequest request) {
boolean flag = false;
String encoding = request.getHeader("Accept-Encoding");
if (encoding.indexOf("gzip") != -1) {
flag = true;
}
return flag;
}

@Override
public void destroy() {
}

}

class MyResponse extends HttpServletResponseWrapper {
private ByteArrayOutputStream baout = new ByteArrayOutputStream();

public MyResponse(HttpServletResponse response) {
super(response);
}

@Override
public ServletOutputStream getOutputStream() throws IOException {
return new MyOutputStream(baout);
}

public ByteArrayOutputStream getBaout() {
if (pw != null) {
pw.flush();
//这里很重要,如果不flush或close,不把字符流刷出去,baout中是不会有数据的.
}
return baout;
}

private PrintWriter pw;

@Override
public PrintWriter getWriter() throws IOException {
pw = new PrintWriter(new OutputStreamWriter(baout, "utf-8"), true);
return pw;
}

}

class MyOutputStream extends ServletOutputStream {
private ByteArrayOutputStream baout = null;

public MyOutputStream(ByteArrayOutputStream baout) {
this.baout = baout;
}

@Override
public void write(int b) throws IOException {
baout.write(b);
}
}


最后在web.xml中配置一下

<!-- gzip压缩 减少网络流量,加快响应速度 -->
<filter>
<filter-name>gzip</filter-name>
<filter-class>com.educate.web.filter.GzipFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>gzip</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  filter 压缩 gzip