为什么要开启Gzip ?
gzip是http协议中使用的一种加密算法,客户端向web服务器端发出了请求后,通常情况下服务器端会将页面文件和其他资源,返回到客户端,客户端加载后渲染呈现,这种情况文件一般都比较大,如果开启Gzip ,那么服务器端响应后,会将页面,JS,CSS等文本文件或者其他文件通过高压缩算法将其压缩,然后传输到客户端,由客户端的浏览器负责解压缩与呈现。通常能节省40%以上的流量(一般都有60%左右),一些PHP,JSP文件也能够进行压缩。
那怎么开启呢?
Tomcat 开启Gzip :
1.找到Tomcat 目录下的conf下的server.xml,并找到如下信息
将它改成如下的形式(其实在上面代码的下面已经有了,将他们打开而已。):
这样,就能够对html和xml进行压缩了,如果要压缩css 和 js,那么需要将
compressableMimeType=”text/html,text/xml”加入css和js:
你甚至可以压缩图片:
compressableMimeType=”text/html,text/xml”加入css和js:
——开启后——–
开启后重启Tomcat ,通过浏览器查看headers信息就能看到是否开启(firebug中有),如果开启了,那么transfer-encoding就会是Gzip,否则就是chunked。
以上方式依赖了tomcat服务器的特性,如果你服务器是iis或者websphere那么还有不同的配置方式,下面我们使用filter,在代码级别完成web应用的gzip压缩的开启.
实现定制输出的关键是对HttpServletResponse 进行包装,截获所有的输出,等到过滤器链处理完毕后,再对截获的输出进行处理,并写入到真正的HttpServletResponse 对象中。JavaEE 框架已经定义了一个HttpServletResponseWrapper 类使得包装HttpServletResponse 更加容易。我们扩展这个HttpServletResponseWrapper,截获所有的输出,并保存到ByteArrayOutputStream 中
步骤:
1.Wrapper 用来包装HttpServletResponse 对象
package com.shop.gzip;
import java.io.ByteArrayOutputStream;
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 Wrapper extends HttpServletResponseWrapper {
public static final int OT_NONE = 0, OT_WRITER = 1, OT_STREAM = 2;
private int outputType = OT_NONE;
private ServletOutputStream output = null;
private PrintWriter writer = null;
private ByteArrayOutputStream buffer = null;
public Wrapper(HttpServletResponse resp) throws IOException {
super(resp);
buffer = new ByteArrayOutputStream();
}
public PrintWriter getWriter() throws IOException {
if (outputType == OT_STREAM)
throw new IllegalStateException();
else if (outputType == OT_WRITER)
return writer;
else {
outputType = OT_WRITER;
writer = new PrintWriter(new OutputStreamWriter(buffer,
getCharacterEncoding()));
return writer;
}
}
public ServletOutputStream getOutputStream() throws IOException {
if (outputType == OT_WRITER)
throw new IllegalStateException();
else if (outputType == OT_STREAM)
return output;
else {
outputType = OT_STREAM;
output = new WrappedOutputStream(buffer);
return output;
}
}
public void flushBuffer() throws IOException {
if (outputType == OT_WRITER)
writer.flush();
if (outputType == OT_STREAM)
output.flush();
}
public void reset() {
outputType = OT_NONE;
buffer.reset();
}
public byte[] getResponseData() throws IOException {
flushBuffer();
return buffer.toByteArray();
}
class WrappedOutputStream extends ServletOutputStream {
private ByteArrayOutputStream buffer;
public WrappedOutputStream(ByteArrayOutputStream buffer) {
this.buffer = buffer;
}
public void write(int b) throws IOException {
buffer.write(b);
}
public byte[] toByteArray() {
return buffer.toByteArray();
}
}
}
2.过滤器
package com.shop.gzip;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
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;
public class GZipFilter implements Filter {
public void destroy() {
}
/**
* 判断浏览器是否支持GZIP
* @param request
* @return
*/
private static boolean isGZipEncoding(HttpServletRequest request){
boolean flag=false;
String encoding=request.getHeader("Accept-Encoding");
if(encoding.indexOf("gzip")!=-1){
flag=true;
}
return flag;
}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletResponse resp = (HttpServletResponse) response;
HttpServletRequest req=(HttpServletRequest)request;
if(isGZipEncoding(req)){
Wrapper wrapper = new Wrapper(resp);
chain.doFilter(request, wrapper);
byte[] gzipData = gzip(wrapper.getResponseData());
resp.addHeader("Content-Encoding", "gzip");
resp.setContentLength(gzipData.length);
ServletOutputStream output = response.getOutputStream();
output.write(gzipData);
output.flush();
} else {
chain.doFilter(request, response);
}
}
public void init(FilterConfig arg0) throws ServletException {
}
private byte[] gzip(byte[] data) {
ByteArrayOutputStream byteOutput = new ByteArrayOutputStream(10240);
GZIPOutputStream output = null;
try {
output = new GZIPOutputStream(byteOutput);
output.write(data);
} catch (IOException e) {
} finally {
try {
output.close();
} catch (IOException e) {
}
}
return byteOutput.toByteArray();
}
}
3.在web.xml中配置 GZipFilter,当我们访问应用中以.html结尾的资源的使用,服务器端就开启httpgzip压缩,将压缩后的信息通过http 协议传递给浏览器.
<filter>
<filter-name>ecsideExport</filter-name>
<filter-class>cn.com.xinli.test.GZipFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>ecsideExport</filter-name>
<url-pattern>*.html</url-pattern>
</filter-mapping>
测试: 首先下载ieHttpHeader 插件.
测试地址:
http://localhost:9090/dwr/test.html
1.未开启http gzip 压缩
GET /dwr/test.html HTTP/1.1
Accept: */*
Accept-Language: zh-cn
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)
Host: localhost:9090
Connection: Keep-Alive
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
ETag: W/"5060-1242444154000"
Last-Modified: Sat, 16 May 2009 03:22:34 GMT
Content-Type: text/html
Content-Length: 5060
Date: Mon, 18 May 2009 12:29:49 GMT
2.开启http gzip 压缩
GET /dwr/test.html HTTP/1.1
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*
Accept-Language: zh-cn
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)
Host: localhost:9090
Connection: Keep-Alive
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
ETag: W/"5060-1242444154000"
Last-Modified: Sat, 16 May 2009 03:22:34 GMT
Content-Encoding: gzip
Content-Type: text/html
Content-Length: 837
Date: Mon, 18 May 2009 12:27:33 GMT
效果是非常明显的..........
上文转载于:http://blog.163.com/biaozongchen/blog/static/135986820101281369363/