1. 程式人生 > >基於Filter實現Gzip數據壓縮

基於Filter實現Gzip數據壓縮

style ont bytes return Coding util 進行 ansi response

在web開發中,當服務器端向客戶端返回的數據量比較大時,我們可以通過Gzip對數據進行壓縮處理

註意:如果小數據量進行壓縮,壓縮後的數據可能比原始數據還大;所以response返回數據量比較小時不推薦使用

這裏代碼結構,紅叉不需要關註,這裏maven環境的問題,不影響我們的主線

技術分享圖片

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns="http://java.sun.com/xml/ns/javaee" 
    xsi:schemaLocation
="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0"> <display-name>gzipfilter</display-name> <filter> <filter-name>gzip</filter-name> <filter-class>gzipfilter.GzipFilter</filter-class> </filter> <filter-mapping> <filter-name>gzip</filter-name> <url-pattern>/servlet/*
</url-pattern> </filter-mapping> <servlet> <servlet-name>TestServlet</servlet-name> <servlet-class>gzipfilter.TestServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>TestServlet</servlet-name> <url-pattern>/servlet/test</url-pattern> </servlet-mapping> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> </web-app>

pom.xml

    <dependencies>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
            <type>jar</type>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
            <version>2.5</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>javax.servlet.jsp</groupId>
            <artifactId>jsp-api</artifactId>
            <version>2.1</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>

GzipFilter

public class GzipFilter implements Filter{

    public void init(FilterConfig config) throws ServletException {
        
    }

    public void destroy() {
        
    }

    public void doFilter(ServletRequest req, ServletResponse res,
            FilterChain chain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) res;
        ResponseWrapper responseWrapper = new ResponseWrapper(response);
        
        chain.doFilter(request, responseWrapper);//通過過濾器  把響應數據寫進自己的response中
        
        //獲得響應數據
        ByteArrayOutputStream buffer=responseWrapper.getBuffer();
        byte[] bytes=buffer.toByteArray();
        
        //壓縮
        ByteArrayOutputStream baout=new ByteArrayOutputStream();
        GZIPOutputStream gout=new GZIPOutputStream(baout);
        gout.write(bytes);
        gout.close();//拿到壓縮後的數據----響應前端
        byte[] gzipbytes = baout.toByteArray();
        response.setHeader("Content-Encoding", "gzip");
        System.out.println(gzipbytes.length+"-------------壓縮後");
        response.getOutputStream().write(gzipbytes);
        
    }
}
/**
 * 
 * 對原始response進行包裝
 *
 */
class ResponseWrapper extends HttpServletResponseWrapper {
    
    private ByteArrayOutputStream buffer = new ByteArrayOutputStream();
    private PrintWriter pw;

    public ResponseWrapper(HttpServletResponse response) {
        super(response);
    }
     
    @Override
    public ServletOutputStream getOutputStream() throws IOException {
        OutputStreamWrapper out = new OutputStreamWrapper(buffer);
        return out;
    }
    
    @Override
    public PrintWriter getWriter() throws IOException {
        if(pw==null){
            OutputStreamWrapper out = new OutputStreamWrapper(buffer);
            pw = new PrintWriter(new OutputStreamWriter(out, "UTF-8"));
        }
        return pw;
    }
    
    public ByteArrayOutputStream getBuffer(){
        return buffer;
    }
}

/**
 * 
 * 包裝 outputStream
 *
 */
class OutputStreamWrapper extends ServletOutputStream{
    
    private ByteArrayOutputStream buffer;
    
    public OutputStreamWrapper(ByteArrayOutputStream buffer) {
         super();
         this.buffer=buffer;
    }

    @Override
    public void write(int b) throws IOException {
        this.buffer.write(b);
    }
    
}

TestServlet

public class TestServlet extends HttpServlet {
     
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        String name="a";
        for(int i=0;i<10;i++){
            name=name+name;
        }
        System.out.println(name.getBytes().length+"==============壓縮前");
        response.getOutputStream().write(name.getBytes());
    }

     
    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }
 
}

index.jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title>My JSP index.jsp starting page</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
</head>
<body>
  <a href="servlet/test">點點</a>
</body>
</html>

結果:

技術分享圖片

基於Filter實現Gzip數據壓縮