提出问题
如果静态文件比较大(比如超过 1M),如果让 tomcat 进行 gzip 压缩,需要消耗 CPU,尤其是访问量较大
如何避免消耗 CPU
分析
提前将 体积大 的静态文件,进行 gzip 压缩
当浏览器发请求时,由 过滤器 拦截,发现读取该文件,就不用 tomcat处理,而是由 过滤器 读取 gzip 文件,并发送给浏览器
解决
代码
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.logging.Logger;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletContext;
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;
public class GzipFilter implements Filter {
private ServletContext ctx;
private Logger logger = Logger.getLogger(GzipFilter.class.getName());
private String contextPath;
@Override
public void destroy() {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse res = (HttpServletResponse) response;
String uri = req.getRequestURI();
String accept = req.getHeader("Accept-Encoding");
InputStream in = null;
contextPath = ctx.getContextPath();
uri = uri.substring(contextPath.length());
if (accept != null && accept.contains("gzip") && (in = ctx.getResourceAsStream(uri + ".gz")) != null) {
logger.info("start getting gzip file "+uri);
ByteArrayOutputStream bout = new ByteArrayOutputStream();
byte[] b = new byte[1024 * 8];
int read = 0;
while ((read = in.read(b)) >= 0) {
bout.write(b, 0, read);
}
in.close();
res.setHeader("Content-Encoding", "gzip");
res.setContentType("application/javascript;charset=UTF-8");
res.setContentLength(bout.size());
ServletOutputStream out = res.getOutputStream();
out.write(bout.toByteArray());
out.flush();
logger.info("finish getting gzip file "+uri);
return;
} else {
chain.doFilter(request, response);
}
}
@Override
public void init(FilterConfig config) throws ServletException {
ctx = config.getServletContext();
}
}
配置web.xml
<!-- read the precompressed gzip js file-->
<filter>
<filter-name>gzip</filter-name>
<filter-class>GzipFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>gzip</filter-name>
<url-pattern>*.js</url-pattern>
</filter-mapping>
测试
压缩js文件,比如:a.js 压缩为 a.js.gz 文件
浏览器访问是否成功