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

tomcat gzip 网页压缩技术

2012-02-12 03:10 344 查看
 gzip是http协议中使用的一种加密算法,客户端向web服务器端发出了请求后,通常情况下服务器端会将页面文件和其他资源,返回到客户端,客户端加载后渲染呈现,这种情况文件一般都比较大,如果开启Gzip ,那么服务器端响应后,会将页面,JS,CSS等文本文件或者其他文件通过高压缩算法将其压缩,然后传输到客户端,由客户端的浏览器负责解压缩与呈现。通常能节省40%以上的流量(一般都有60%左右),一些PHP,JSP文件也能够进行压缩。
1.Tomcat 直接开启Gzip

打开Tomcat 目录下的conf下的server.xml,并找到如下信息:

Xml代码

<!-- Note : To use gzip compression you could set the following properties :

compression="on"
compressionMinSize="2048"

noCompressionUserAgents="gozilla, traviata"

compressableMimeType="text/html,text/xml"

-->

<!-- Note : To use gzip compression you could set the following properties : compression="on" compressionMinSize="2048" noCompressionUserAgents="gozilla, traviata" compressableMimeType="text/html,text/xml" -->


把它们加入到你配置的<Connector port="80" .../>中去。如果要压缩css 和 js,加入compressableMimeType="text/html,text/xml,text/css,text/javascript"。还要压缩图片,加入compressableMimeType="text/html,text/xml,text/css,text/javascript,image/gif,image/jpg"。

开启后重启Tomcat ,通过浏览器查看headers信息就能看到是否开启。

2.使用filter,在代码级别完成web应用的gzip压缩的开启。

(1).CachedResponseWrapper类

实现定制输出的关键是对HttpServletResponse 进行包装,截获所有的输出,等到过滤器链处理完毕后,再对截获的输出进行处理,并写入到真正的HttpServletResponse 对象中。JavaEE 框架已经定义了一个HttpServletResponseWrapper 类使得包装HttpServletResponse 更加容易。我们扩展这个HttpServletResponseWrapper,截获所有的输出,并保存到ByteArrayOutputStream 中。

定制的包装响应能方便地从帮助类 HttpServletResponseWrapper 中导出。这一类粗略地执行许多方法,允许我们简单地覆盖 getOutputStream() 方法以及 getWriter() 方法,提供了定制输出流的实例。

HttpServletResponseWrapper这个类的使用包括以下五个步骤:

1)建立一个响应包装器。扩展javax.servlet.http.HttpServletResponseWrapper。

2)提供一个缓存输出的PrintWriter。重载getWriter方法,返回一个保存发送给它的所有东西的PrintWriter,并把结果存进一个可以稍后访问的字段中。

3)传递该包装器给doFilter。此调用是合法的,因为HttpServletResponseWrapper实现HttpServletResponse。

4)提取和修改输出。在调用FilterChain的doFilter方法后,原资源的输出只要利用步骤2中提供的机制就可以得到。只要对你的应用适合,就可以修改或替换它。

5)发送修改过的输出到客户机。因为原资源不再发送输出到客户机(这些输出已经存放到你的响应包装器中了),所以必须发送这些输出。这样,你的过滤器需要从原响应对象中获得PrintWriter或OutputStream,并传递修改过的输出到该流中。

Java代码

class CachedResponseWrapper extends
HttpServletResponseWrapper {

public static final int
OUTPUT_NONE = 0;

public static final int
OUTPUT_WRITER = 1;

public static final int
OUTPUT_STREAM = 2;
private int outputType = OUTPUT_NONE;

private int status = SC_OK;

private ServletOutputStream output = null;

private PrintWriter writer = null;

private ByteArrayOutputStream buffer =
null;
public CachedResponseWrapper(HttpServletResponse resp)
throws IOException {
super(resp);
buffer = new ByteArrayOutputStream();
}
public int getStatus() {
return status;
}
public void setStatus(int
status) {
super.setStatus(status);
this.status = status;
}
public void setStatus(int
status, String string) {
super.setStatus(status, string);
this.status = status;
}
public void sendError(int
status, String string) throws IOException {

super.sendError(status, string);
this.status = status;
}
public void sendError(int
status) throws IOException {
super.sendError(status);
this.status = status;
}
public void sendRedirect(String location)
throws IOException {
super.sendRedirect(location);
this.status = SC_MOVED_TEMPORARILY;
}
public PrintWriter getWriter() throws
IOException {
if (outputType == OUTPUT_STREAM)
throw new IllegalStateException();

else if (outputType == OUTPUT_WRITER)

return writer;
else {
outputType = OUTPUT_WRITER;
writer = new PrintWriter(new
OutputStreamWriter(buffer,
getCharacterEncoding()));
return writer;
}
}
public ServletOutputStream getOutputStream()
throws IOException {
if (outputType == OUTPUT_WRITER)
throw new IllegalStateException();

else if (outputType == OUTPUT_STREAM)

return output;
else {
outputType = OUTPUT_STREAM;
output = new WrappedOutputStream(buffer);

return output;
}
}
public void flushBuffer()
throws IOException {
if (outputType == OUTPUT_WRITER)
writer.flush();
if (outputType == OUTPUT_STREAM)
output.flush();
}
public void reset() {
outputType = OUTPUT_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();
}
}
}

class CachedResponseWrapper extends HttpServletResponseWrapper { public static final int OUTPUT_NONE = 0; public static final int OUTPUT_WRITER = 1; public static final int OUTPUT_STREAM = 2; private int outputType = OUTPUT_NONE; private int status = SC_OK; private ServletOutputStream output = null; private PrintWriter writer = null; private ByteArrayOutputStream buffer = null; public CachedResponseWrapper(HttpServletResponse resp) throws IOException { super(resp); buffer = new ByteArrayOutputStream(); } public int getStatus() { return status; } public void setStatus(int status) { super.setStatus(status); this.status = status; } public void setStatus(int status, String string) { super.setStatus(status, string); this.status = status; } public void sendError(int status, String string) throws IOException { super.sendError(status, string); this.status = status; } public void sendError(int status) throws IOException { super.sendError(status); this.status = status; } public void sendRedirect(String location) throws IOException { super.sendRedirect(location); this.status = SC_MOVED_TEMPORARILY; } public PrintWriter getWriter() throws IOException { if (outputType == OUTPUT_STREAM) throw new IllegalStateException(); else if (outputType == OUTPUT_WRITER) return writer; else { outputType = OUTPUT_WRITER; writer = new PrintWriter(new OutputStreamWriter(buffer, getCharacterEncoding())); return writer; } } public ServletOutputStream getOutputStream() throws IOException { if (outputType == OUTPUT_WRITER) throw new IllegalStateException(); else if (outputType == OUTPUT_STREAM) return output; else { outputType = OUTPUT_STREAM; output = new WrappedOutputStream(buffer); return output; } } public void flushBuffer() throws IOException { if (outputType == OUTPUT_WRITER) writer.flush(); if (outputType == OUTPUT_STREAM) output.flush(); } public void reset() { outputType = OUTPUT_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).GZipFilter类

Java代码

public class GZipFilter implements
Filter {
public void init(FilterConfig arg0)
throws ServletException {
}
public void doFilter(ServletRequest request, ServletResponse response,

FilterChain chain) throws IOException, ServletException {

HttpServletResponse httpResponse = (HttpServletResponse) response;

CachedResponseWrapper wrapper = new CachedResponseWrapper(httpResponse);

// 写入wrapper:
chain.doFilter(request, wrapper);
// 对响应进行处理,这里是进行GZip压缩:
byte[] data = GZipUtil.gzip(wrapper.getResponseData());

httpResponse.setHeader("Content-Encoding",
"gzip");
httpResponse.setContentLength(data.length);
ServletOutputStream output = response.getOutputStream();
output.write(data);
output.flush();
}
public void destroy() {
}
}

public class GZipFilter implements Filter { public void init(FilterConfig arg0) throws ServletException { } public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletResponse httpResponse = (HttpServletResponse) response; CachedResponseWrapper wrapper = new CachedResponseWrapper(httpResponse); // 写入wrapper: chain.doFilter(request, wrapper); // 对响应进行处理,这里是进行GZip压缩: byte[] data = GZipUtil.gzip(wrapper.getResponseData()); httpResponse.setHeader("Content-Encoding", "gzip"); httpResponse.setContentLength(data.length); ServletOutputStream output = response.getOutputStream(); output.write(data); output.flush(); } public void destroy() { } }


(3).GZipUtil类

Java代码

public final class GZipUtil {

public static byte[] gzip(byte[] data) {

ByteArrayOutputStream byteOutput = new ByteArrayOutputStream(10240);

GZIPOutputStream output = null;
try {
output = new GZIPOutputStream(byteOutput);

output.write(data);
} catch (IOException e) {
throw new RuntimeException("G-Zip failed.", e);

} finally {
if (output != null) {

try {
output.close();
} catch (IOException e) {
}
}
}
return byteOutput.toByteArray();
}
}

public final class GZipUtil { public static byte[] gzip(byte[] data) { ByteArrayOutputStream byteOutput = new ByteArrayOutputStream(10240); GZIPOutputStream output = null; try { output = new GZIPOutputStream(byteOutput); output.write(data); } catch (IOException e) { throw new RuntimeException("G-Zip failed.", e); } finally { if (output != null) { try { output.close(); } catch (IOException e) { } } } return byteOutput.toByteArray(); } }


(4).在web.xml中配置 GZipFilter

Xml代码

<filter>
<filter-name>GZipFilter</filter-name>

<filter-class>com.logcd.filter.GZipFilter</filter-class>

</filter>
<filter-mapping>
<filter-name>GZipFilter</filter-name>

<url-pattern>*.html</url-pattern>

</filter-mapping>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息