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>
控制台输出(显示压缩的效果)
浏览器输出(显示响应报文)