欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Java使用GZIP进行压缩和解压

程序员文章站 2024-02-29 09:41:40
...

附加java源码包下载地址

网页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 继承
HttpServletResponseWrapper
因为在
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>


可以下载http://download.csdn.net/download/sinat_36596988/10232572