filter攔截(Response輸出壓縮)此案例基礎知識面廣

dhzbkj發表於2018-06-05
Response兩種輸出方式:1.getOutputStream().writer();2.getWriter().writer();但不能同時存在
1.配置檔案
<filter>
    <filter-name>GzipFilter</filter-name>
    <filter-class>cn.itcast.web.filter.GzipFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>GzipFilter</filter-name>
    <url-pattern>*.jsp</url-pattern><!-- 注意一般不要做全棧壓縮,只壓縮html,jsp,js -->
    <dispatcher>FORWARD</dispatcher>
    <dispatcher>REQUEST</dispatcher>
</filter-mapping>
<filter-mapping>
    <filter-name>GzipFilter</filter-name>
    <url-pattern>*.html</url-pattern>
</filter-mapping>
<filter-mapping>
    <filter-name>GzipFilter</filter-name>
    <url-pattern>*.js</url-pattern>
</filter-mapping>
2.定義GzipFilter類並 implements Filter
 public class GzipFilter implements Filter {
@Override
    public void doFilter(ServletRequest req, ServletResponse resp,FilterChain chain) throws IOException, ServletException {
        HttpServletRequest request=(HttpServletRequest) req;
        HttpServletResponse response=(HttpServletResponse) resp;
          MyResponse myresponse=new MyResponse(response);
        chain.doFilter(request,myresponse);    //response.getWriterresponse.getOutputStream
            //取出緩衝資料壓縮後輸出
            byte out[]=myresponse.getBuffer();
            System.out.println("壓縮前:"+out.length);
            byte gzipout[]=gzip(out);
            System.out.println("壓縮後:"+gzipout.length);
            //設定頭資訊,以壓縮方式開啟  
            response.setHeader("content-encoding", "gzip");
            response.setHeader("content-length", gzipout.length+"");
 
            response.getOutputStream().write(gzipout);    //分別對應下面橙色A/B/C
    }
public byte[] gzip(byte b[]) throws IOException{    //壓縮
    ByteArrayOutputStream bout=new ByteArrayOutputStream();
    GZIPOutputStream gout=new GZIPOutputStream(bout);
gout.write(b);
gout.close();
return bout.toByteArray();
}
 
class MyResponse extends HttpServletResponseWrapper{    //A處對應上面response
    private ByteArrayOutputStream bout=new ByteArrayOutputStream();    //定義緩衝區陣列位元組流
        private PrintWriter pw;
        private HttpServletResponse response;
    public MyResponse(HttpServletResponse response) {
        super(response);
        this.response=response;
    }
//response輸出資料方式一:response.getOutputStream().write("xxxx");
@Override
public ServletOutputStream getOutputStream() throws IOException {    //B處對應上面getOutputStream
    return new MyServletOutputStream(bout); //response.getOutputStream.write(); 因ServletOutputStream是abstract類,不能直接 new
    }

//response輸出資料方式二:response.getWriter().write("xxxx");
@Override
public PrintWriter getWriter() throws IOException{
    //pw=new PrintWriter(bout);//字元流向位元組流寫資料,會查編碼,預設GB2312,所以要注意亂碼問題
    pw=new PrintWriter(new OutputStreamWriter(bout,response.getCharacterEncoding()));    //用於解決PrintWriter().writer()的亂碼問題
    return pw;    //MyResponse.getWriter.write("xxx");
}
//將緩衝區中的資料返回
public byte[] getBuffer(){
    if(pw!=null){    
    pw.close();    //保證資料會寫入緩衝區,當用PrintWrier輸出時,此判斷有效
    }
        return bout.toByteArray();  
    }
}

class MyServletOutputStream extends ServletOutputStream{    //B處對應上面getOutputStream
    private ByteArrayOutputStream bout;
     public MyServletOutputStream(ByteArrayOutputStream bout){
           this.bout=bout;
   }
@Override
         public void write(int b) throws IOException {  //覆寫write方法//c處對應上面write
             bout.write(b);
    }
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
// TODO Auto-generated method stub

}

@Override
public void destroy() {
// TODO Auto-generated method stub

}

}

3.Servlet程式碼編寫
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {

String data="中國";
//response.getOutputStream().write(data.getBytes("UTF-8"));//一定要指編碼,用於解決getOutputStream().write輸出亂碼
response.getWriter().write(data); //getWriter().writer輸出的亂碼問題在攔截程式碼中處理。
}

相關文章