package com.itheima.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.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponseWrapper; public class GzipFilter implements Filter { private FilterConfig config; @Override public void init(FilterConfig filterConfig) throws ServletException { this.config = filterConfig; } @Override public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) req; HttpServletResponse response = (HttpServletResponse) resp; String encoding = config.getInitParameter("encoding"); request.setCharacterEncoding(encoding); response.setContentType("text/html;charset="+encoding); // // response.setCharacterEncoding("") // HttpServletRequestWrapper ---对request 进行 包装的包装类 ---- 解决全站的 请求数据的乱码 //HttpServletResponseWrapper ----对response 进行 包装的 包装类 ---- 解决全站的 响应的数据的 压缩 MyHttpServletResponseWrapper myresponse = new MyHttpServletResponseWrapper(response); //放行 chain.doFilter(request, myresponse); // --- 目标 资源会得到 执行 System.out.println("之后 ..."); // 将 写到 myresponse 里的数据 进行 压缩 , 然后 输出到 浏览器 去 //这里 报错的 原因是 因为 // 没有 原始的数据(压缩前的数据), 那么 如果 能够 将原始的 压缩前的数据 拿到 // 所有的问题就 都解决了... // byte[] b = data.getBytes(); byte[] b = myresponse.getOldData(); System.out.println("压缩前: " + b.length); //底层流 ByteArrayOutputStream baos = new ByteArrayOutputStream(); //采用gzip压缩 //这里 压缩的时候, 需要的是一个 输出流, 这里的输出流是一个底层流 GZIPOutputStream gout= new GZIPOutputStream(baos); gout.write(b); gout.close(); //确保 数据可以写到 底层流 baos中去 //这里 要注意: 由于 数据是写到 底层流 baos中去的, gout 默认的是有 缓冲区的 . b = baos.toByteArray(); System.out.println("压缩后 : " +b.length); //告诉浏览器 需要 解压缩 数据-- 通过 http的响应头 实现 response.setHeader("content-encoding", "gzip"); response.setContentLength(b.length); //数据的长度 response.getOutputStream().write(b); } @Override public void destroy() { } } class MyHttpServletResponseWrapper extends HttpServletResponseWrapper{ private HttpServletResponse response; public MyHttpServletResponseWrapper(HttpServletResponse response) { super(response); this.response= response; } ByteArrayOutputStream bout = new ByteArrayOutputStream(); //通过 这个方法 可以 拿到 原始的 数据 public byte[] getOldData(){ if(pw!=null){ pw.close(); } return bout.toByteArray(); } PrintWriter pw = null; @Override public PrintWriter getWriter() throws IOException { //字符输出流, 有缓冲区 , if(pw==null){ //字符输出流 ----- bout (字节流) pw = new PrintWriter(new OutputStreamWriter(bout, response.getCharacterEncoding())); } return pw; } @Override public ServletOutputStream getOutputStream() throws IOException { //在 调用这个 方法的时候, 数据 写到 一个 俺们自己 定义的输出流去, 那么这样 数据就进入了 自己 定义的输出流中去 了 . return new MyServletOutputStream(bout); } } class MyServletOutputStream extends ServletOutputStream{ private OutputStream out; public MyServletOutputStream(OutputStream out){ this.out = out; } //最终 是 调用到 这个 方法里 了 . //所有的数据 都进入 到了 out 中去 了,而这里 out 又 是 MyHttpServletResponseWrapper 里的 bout 了, 所以 所有的数据 都 在 bout 中了 @Override public void write(int b) throws IOException { out.write(b); } // 这里 没有 一个 接受 字节 数组的write 方法 }
0则评论给“Filter过滤器(gzip) 全站 压缩”