maxThreads="150"minSpareThreads="25"maxSpareThreads="75"
enableLookups="false"redirectPort="8443"acceptCount="100"
connectionTimeout="20000"disableUploadTimeout="true"URIEncoding="utf-8"
compression="on"
compressionMinSize="2048"
noCompressionUserAgents="gozilla,traviata"
compressableMimeType="text/html,text/xml"/>
我们为Connector添加了如下几个属性,他们意义分别是:
compression="on"打开压缩功能
compressionMinSize="2048"启用压缩的输出内容大小,这里面默认为2KB
noCompressionUserAgents="gozilla,traviata"对于以下的浏览器,不启用压缩
compressableMimeType="text/html,text/xml,image/png" 压缩类型
有时候,我们无法配置server.xml,比如如果我们只是租用了别人的空间,但是它并没有启用GZIP,那么我们就要使用程序启用GZIP功能。
我们将需要压缩的文件,放到指定的文件夹,使用一个过滤器,过滤对这个文件夹里文件的请求。
清单9.自定义Filter压缩GZIP
//监视对gzipCategory文件夹的请求
@WebFilter(urlPatterns={"/gzipCategory/*"})
publicclassGZIPFilterimplementsFilter{
@Override
publicvoiddoFilter(ServletRequestrequest,ServletResponseresponse,
FilterChainchain)throwsIOException,ServletException{
Stringparameter=request.getParameter("gzip");
//判断是否包含了Accept-Encoding请求头部
HttpServletRequests=(HttpServletRequest)request;
Stringheader=s.getHeader("Accept-Encoding");
//"1".equals(parameter)只是为了控制,如果传入gzip=1,才执行压缩,目的是测试用
if("1".equals(parameter)&&header!
=null&&header.toLowerCase().contains("gzip")){
HttpServletResponseresp=(HttpServletResponse)response;
finalByteArrayOutputStreambuffer=newByteArrayOutputStream();
HttpServletResponseWrapperhsrw=newHttpServletResponseWrapper(
resp){
@Override
publicPrintWritergetWriter()throwsIOException{
returnnewPrintWriter(newOutputStreamWriter(buffer,
getCharacterEncoding()));
}
@Override
publicServletOutputStreamgetOutputStream()throwsIOException{
returnnewServletOutputStream(){
@Override
publicvoidwrite(intb)throwsIOException{
buffer.write(b);
}
};
}
};
chain.doFilter(request,hsrw);
byte[]gzipData=gzip(buffer.toByteArray());
resp.addHeader("Content-Encoding","gzip");
resp.setContentLength(gzipData.length);
ServletOutputStreamoutput=response.getOutputStream();
output.write(gzipData);
output.flush();
}else{
chain.doFilter(request,response);
}
}
//用GZIP压缩字节数组
privatebyte[]gzip(byte[]data){
ByteArrayOutputStreambyteOutput=newByteArrayOutputStream(10240);
GZIPOutputStreamoutput=null;
try{
output=newGZIPOutputStream(byteOutput);
output.write(data);
}catch(IOExceptione){
}finally{
try{
output.close();
}catch(IOExceptione){
}
}
returnbyteOutput.toByteArray();
}
……
}
该程序的主体思想,是在响应流写回之前,对响应的字节数据进行GZIP压缩,因为并不是所有的浏览器都支持GZIP解压缩,如果浏览器支持GZIP解压缩,会在请求报头的Accept-Encoding里包含gzip。
这是告诉服务器浏览器支持GZIP解压缩,因此如果用程序控制压缩,为了保险起见,还需要判断浏览器是否发送accept-encoding:
gzip报头,如果包含了该报头,才执行压缩。
为了验证压缩前后的情况,使用Firebug监控请求和响应报头。
清单10.压缩前请求
GET/testProject/gzipCategory/test.htmlHTTP/1.1
Accept:
*/*
Accept-Language:
zh-cn
Accept-Encoding:
gzip,deflate
User-Agent:
Mozilla/4.0(compatible;MSIE6.0;WindowsNT5.1;SV1)
Host:
localhost:
9090
Connection:
Keep-Alive
清单11.不压缩的响应
HTTP/1.1200OK
Server:
Apache-Coyote/1.1
ETag:
W/"5060-1242444154000"
Last-Modified:
Sat,16May200903:
22:
34GMT
Content-Type:
text/html
Content-Length:
5060
Date:
Mon,18May200912:
29:
49GMT
清单12.压缩后的响应
HTTP/1.1200OK
Server:
Apache-Coyote/1.1
ETag:
W/"5060-1242444154000"
Last-Modified:
Sat,16May200903:
22:
34GMT
Content-Encoding:
gzip
Content-Type:
text/html
Content-Length:
837
Date:
Mon,18May200912:
27:
33GMT
可以看到,压缩后的数据比压缩前数据小了很多。
压缩后的响应报头包含Content-Encoding:
gzip。
同时Content-Length包含了返回数据的大小。
GZIP压缩是一个重要的功能,前面提到的是对单一服务器的压缩优化,在高并发的情况,多个Tomcat服务器之前,需