最近看到一段代码是用GZIP压缩Filter,具体代码有三部分
1
package com.helloweenvsfei.gzip;
import java.io.IOException;
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;
public class GZipFilter implements Filter {
public void destroy() {
}
public void doFilter(ServletRequest req, ServletResponse res,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
String acceptEncoding = request.getHeader("Accept-Encoding");
System.out.println("Accept-Encoding: " + acceptEncoding);
if (acceptEncoding != null
&& acceptEncoding.toLowerCase().indexOf("gzip") != -1) {
// 如果客户浏览器支持 GZIP 格式, 则使用 GZIP 压缩数据
GZipResponseWrapper gzipResponse = new GZipResponseWrapper(response);
chain.doFilter(request, gzipResponse);
// 输出压缩数据
gzipResponse.finishResponse();
} else {
// 否则, 不压缩
chain.doFilter(request, response);
}
}
public void init(FilterConfig arg0) throws ServletException {
}
}
2
package com.helloweenvsfei.gzip;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.zip.GZIPOutputStream;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
public class GZipOutputStream extends ServletOutputStream {
private HttpServletResponse response;
// JDK 自带的压缩数据的类
private GZIPOutputStream gzipOutputStream;
// 将压缩后的数据存放到 ByteArrayOutputStream 对象中
private ByteArrayOutputStream byteArrayOutputStream;
public GZipOutputStream(HttpServletResponse response) throws IOException {
this.response = response;
byteArrayOutputStream = new ByteArrayOutputStream();
gzipOutputStream = new GZIPOutputStream(byteArrayOutputStream);
}
public void write(int b) throws IOException {
gzipOutputStream.write(b);
}
public void close() throws IOException {
// 压缩完毕 一定要调用该方法
gzipOutputStream.finish();
// 将压缩后的数据输出到客户端
byte[] content = byteArrayOutputStream.toByteArray();
// 设定压缩方式为 GZIP, 客户端浏览器会自动将数据解压
response.addHeader("Content-Encoding", "gzip");
response.addHeader("Content-Length", Integer.toString(content.length));
// 输出
ServletOutputStream out = response.getOutputStream();
out.write(content);
out.close();
}
public void flush() throws IOException {
gzipOutputStream.flush();
}
public void write(byte[] b, int off, int len) throws IOException {
gzipOutputStream.write(b, off, len);
}
public void write(byte[] b) throws IOException {
gzipOutputStream.write(b);
}
}
3.
package com.helloweenvsfei.gzip;
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 GZipResponseWrapper extends HttpServletResponseWrapper {
// 默认的 response
private HttpServletResponse response;
// 自定义的 outputStream, 执行close()的时候对数据压缩,并输出
private GZipOutputStream gzipOutputStream;
// 自定义 printWriter,将内容输出到 GZipOutputStream 中
private PrintWriter writer;
public GZipResponseWrapper(HttpServletResponse response) throws IOException {
super(response);
this.response = response;
}
public ServletOutputStream getOutputStream() throws IOException {
if (gzipOutputStream == null)
gzipOutputStream = new GZipOutputStream(response);
return gzipOutputStream;
}
public PrintWriter getWriter() throws IOException {
if (writer == null)
writer = new PrintWriter(new OutputStreamWriter(
new GZipOutputStream(response), "UTF-8"));
return writer;
}
// 压缩后数据长度会发生变化 因此将该方法内容置空
public void setContentLength(int contentLength) {
}
public void flushBuffer() throws IOException {
gzipOutputStream.flush();
}
public void finishResponse() throws IOException {
if (gzipOutputStream != null)
gzipOutputStream.close();
if (writer != null)
writer.close();
}
}
通过查询JAVA API得知:
finish()
完成将压缩数据写入输出流的操作,无需关闭基础流
[url=mk:@MSITStore:D:\20120617\学习资料\参考手册\JAVA%20API官方文档中文版.CHM::/java/util/zip/GZIPOutputStream.html#write(byte[], int, int)]write[/url](byte[] buf, int off, int len)
将字节数组写入压缩输出流。
请问GZipOutputStream中的gzipOutputStream = new GZIPOutputStream(byteArrayOutputStream);是如何将数据压缩的,调用finish()的时候都完成了哪些动作呢?
|