Java使用GZIP进行压缩和解压
程序员文章站
2024-02-29 09:41:40
...
网页GZIP压缩可以提高网页浏览速度,无论是之前在如何做网站课程中说的精简代码、图片无损压缩都不如启用Gzip来的实在。只要服务器开启了GZIP压缩,那么浏览器接收的就是压缩的内容,而开启网页压缩的目的是为了提高网络的传输速度,但会占用一些CPU资源,因为压缩内容需要CPU工作。
先贴出代码
package cn.filter;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
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.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
public class GzipFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
MyResponse resp = new MyResponse((HttpServletResponse)response);
//PS:MyResponse extends HttpServletResponseWrapper不会输出页面内容(因为重写了getOutputStream和getWriter()为了得到字符流) 而 ServletResponse response会(resp不会有内容,response有内容)。
chain.doFilter(request, resp);//通过这句话MyResponse得到字符流,不会输出页面内容(因为重写了getOutputStream和getWriter()为了得到字符流)
//MyResponse得到字符流,下面就可以处理GIZP压缩了、就可以自己输出页面内容了
ByteArrayOutputStream bout = resp.getBout();
byte[] srcBytes = bout.toByteArray();//原来的字节
//下面进行压缩:
ByteArrayOutputStream bout2=new ByteArrayOutputStream();
GZIPOutputStream gout=new GZIPOutputStream(bout2);
gout.write(srcBytes);//把原数据写入gout---bout2
gout.close();
byte[] descBytes=bout2.toByteArray();
//输出之前告诉客户端:我们的数据是gzip格式,然后输出
HttpServletResponse httpResp=(HttpServletResponse) response;
httpResp.setHeader("Content-Encoding", "gzip");
httpResp.setContentLength(descBytes.length);
httpResp.setContentType("text/html;charset=utf-8");
OutputStream out=httpResp.getOutputStream();//拿到字节流,必须是字节流
out.write(descBytes);
}
@Override
public void destroy() {
}
}
class MyResponse extends HttpServletResponseWrapper{
private ByteArrayOutputStream bout;
PrintWriter pw = null;
public MyResponse(HttpServletResponse response) {
super(response);
bout=new ByteArrayOutputStream();
}
public ByteArrayOutputStream getBout() {
//如果是字符数据
if(pw!=null){
pw.close();//要关流刷新
}
return bout;
}
//在这里重写getOutputStream和getWriter方法 这两个方法在GET浏览器数据时会自动调用
//二进制数据
@Override
public ServletOutputStream getOutputStream() throws IOException {
return new MyOutputStream(bout);
}
//字符数据
@Override
public PrintWriter getWriter() throws IOException {
pw=new PrintWriter(new OutputStreamWriter(bout,"utf-8"));//用套接流来进行套接 因为(bout,"utf-8")是字节而printWriter是字符 要套接成字符用OutputStreamwriter
return pw;
}
}
//ServletOutputStream 提供将二进制数据发送到客户端的输出流
class MyOutputStream extends ServletOutputStream{
private ByteArrayOutputStream bout;
public MyOutputStream(ByteArrayOutputStream bout) {
this.bout = bout;
}
@Override
public void write(int b) throws IOException {
bout.write(b);//把数据写入bou字节流里面
}
}
逻辑
1。把chain.doFilter(request, response);的response 继承
可以下载http://download.csdn.net/download/sinat_36596988/10232572HttpServletResponseWrapper
因为在
HttpServletResponseWrapper可以重写getWriter,getOutputStream方法。
通过这些方法获得响应的数据。并且写入
ByteArrayOutputStream bout
2。通过
ByteArrayOutputStream bout=resp.getBout();
byte[] srcBytes=bout.toByteArray();//这是源数据
获取源数据。3 进行数据压缩 并且输出
//下面进行压缩:
ByteArrayOutputStream bout2=new ByteArrayOutputStream();
GZIPOutputStream gout=new GZIPOutputStream(bout2);
gout.write(srcBytes);//把原数据写入gout---bout2
gout.close();
byte[] descBytes=bout2.toByteArray();
//输出之前告诉客户端:我们的数据是gzip格式,然后输出
HttpServletResponse httpResp=(HttpServletResponse) response;
httpResp.setHeader("Content-Encoding", "gzip");
httpResp.setContentLength(descBytes.length);
httpResp.setContentType("text/html;charset=utf-8");
OutputStream out=httpResp.getOutputStream();//拿到字节流,必须是字节流
out.write(descBytes);
然后在web.xml配置拦截<filter>
<filter-name>gzip</filter-name>
<filter-class>cn.controller.GzipFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>gzip</filter-name>
<url-pattern>*.jsp</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>gzip</filter-name>
<url-pattern>*.css</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>gzip</filter-name>
<url-pattern>*.js</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>gzip</filter-name>
<url-pattern>*.jpg</url-pattern>
</filter-mapping>
上一篇: two pointers 双针法