开发了一个Web项目,在IE7和Firefox下测试全部ok,但在Ie6下发现个别画面出现假死机现象,写了一大堆js代码跟踪,发现在js中动态load js文件时,严重超时。而这个现象在tomcat不发生只在jboss中发生。比较tomcat和jboss的配置,发现唯一不同在于jboss启用了gzip
二、 通过程序实现
采用 gzip servlet filter 实现
从 HTTP/1.1 开始,客户端就可以在请求头中添加
Accept-Encoding: gzip,deflate (可以从 HTTP WATCH 中查看发现确实支持)
来向请求的服务器表明自己支持 Gzip 压缩的响应。 Web 服务器则在响应头中添加
Content-Encoding: gzip
来向客户端表明响应体是经过 gzip 压缩的。
程序代码如下:
(在此非常感谢 提供代码)
具体代码如下:
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 页面无效!
应用:
将来可以在站点中编写此类过滤器,将页面内容尽可能地做 GZIP 输出提高下载的速度!