Java代码:response压缩响应

思路:

1、通过filter向目标页面传递一个自定义的response对象 2.、在这个response对象中通过重写getOutputStream方法和getWriter方法使目标资源调用
该方法输出页面内容时,获得我们自定义的ServletOutputStream对象
3、在我们自己定义的ServletOutputStream中,重写writer 方法,使资源写到buffer中。
4、当页面完成输出后,在filter中就可以得到页面写出的数据,从而我们可以调用GZIPOutputStream
对数据进行压缩后再传递给浏览器,完成响应文件的压缩功能

目的:减少浏览器的响应时间以及节省带宽


1、showServlet类:

public class ShowServlet extends HttpServlet {
	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		//获得response的输出流
		ServletOutputStream sout=response.getOutputStream();
		//字符串转化为字节输出
		sout.write("AAAAAAAfwef fds asdfsdaf sdfa sdfasd sadf AAAAAAAAAAAAAAAAAAAAAAAAAAAAA".getBytes());
	}
}


2、MyResponse类:


import java.io.ByteArrayOutputStream;
import java.io.IOException;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;

	/*HttpServletResponseWrapper
	是一个Decoretor设计模式的默认实现类
	不需要像实现request接口中的所有方法
	以下为装饰类的做法
	*/
public class MyResponse extends HttpServletResponseWrapper {
	private HttpServletResponse response;
	private ByteArrayOutputStream bout=new ByteArrayOutputStream();
	
	public MyResponse(HttpServletResponse response) {
		super(response);
		this.response=response;
	}
	
	/*综合考虑下还是重写getOutStream
	但是需求是要输出到缓存,此方法不适合,于是写一个拓展类类来迎合需求*/
	@Override
	public ServletOutputStream getOutputStream() throws IOException {
		return new MyServletOutputStream(bout);
	}
	
	
	//将数据封装成一个数组然后发送到缓存
	class MyServletOutputStream extends ServletOutputStream{
		private ByteArrayOutputStream bout;
		public MyServletOutputStream(ByteArrayOutputStream bout){
			this.bout=bout;
			
		}
		
		/*此处应该要将数据包装成一个数组但是
			此处不符合需求,于是重载*/
		@Override
		public void write(int b) throws IOException {
			
		}
		public void write(byte[] bytes) throws IOException {
			bout.write(bytes);
			bout.flush();
			bout.close();
		}
		
		
	}
	public byte[] getBuffer() {
		return bout.toByteArray();
	}
}



3、GZIPFilter过滤类:



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.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class GZIPFilter implements Filter {
	@Override
	public void destroy() {
	}

	@Override
	public void doFilter(ServletRequest req, ServletResponse res,
			FilterChain chain) throws IOException, ServletException {
	//转化为子类才能处理,此处用了强制类型转换
	HttpServletRequest request=(HttpServletRequest) req;
	HttpServletResponse response=(HttpServletResponse) res;
	
	//创建MyResponse
	MyResponse myResponse=new MyResponse(response);
	
	
	//此处放行的response是处理过的response
	chain.doFilter(request, myResponse);
	
	
	//在输出到浏览器之前将输过来的buffer进行压缩
	//增加getBuffer方法
	byte[] bytes=myResponse.getBuffer();
	//输出压缩前的长度以作对比
	System.out.println("压缩前"+bytes.length);
	
	//用GZIPOutputStream压缩
	ByteArrayOutputStream bout=new ByteArrayOutputStream();
	GZIPOutputStream gzip=new GZIPOutputStream(bout);
	
	gzip.write(bytes);

	//一般输出都要flush
	gzip.flush();
	gzip.close();
	bytes=bout.toByteArray();
	//压缩后
	System.out.println("压缩后"+bytes.length);
	
	//注明压缩类型
	response.setHeader("content-encoding", "gzip");
	response.setHeader("content-length",bytes.length+"");
	//写到浏览器,浏览器会自动解压,只要注明了类型
	response.getOutputStream().write(bytes);
	

	}

	@Override
	public void init(FilterConfig filterConfig) throws ServletException {

	}

}



其中在xml配置文件中应该添加以下代码

	 <filter>
	 	<filter-name>GZIPFilter</filter-name>
	 	<filter-class>a2.GZIPFilter</filter-class>
	 </filter>
	
	<filter-mapping>
		<filter-name>GZIPFilter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>

 



控制台输出(显示压缩的效果)


浏览器输出(显示响应报文)




 

posted @ 2016-01-05 14:30  余***龙  阅读(1890)  评论(0编辑  收藏  举报