2020 年 2 月 24 日 星期一

IT Skills 波林

Polin WEI – 資訊工作者的技術手札

Spring Boot 利用 Filter 與 htmlcompressor 最小化 HTML 網頁Size

1 min read
美國海景

Spring Boot 利用 Filter 與 googlecodehtmlcompressor 最小化 HTML 網頁Size

 

WordPress 利用 gzip 與外掛提升網站速度 中提到,可以將網頁的空白去除,以達到網頁最小的 Size ,進而提升載入網頁的速度,而在 Spring boot 中也可以透過 javax.servlet.Filter 及使用 com.googlecode.htmlcompressor 來達到這個功能。

 

  • 攔截器 ( Interceptor )  與 篩選器 ( Filter )

在實作之前,我們先瞭解一下攔截器 ( Interceptor )  與篩選器 ( Filter ) 。這兩者在功能方面很類似,但是在具體技術實現方面,還是有差異的,兩者的主要區別包括以下幾個方面:

  1. Filter 是依賴於 Servlet 容器,屬於 Servlet 規範的一部分,而攔截器則是獨立存在的,可以在任何情況下使用。
  2. Filter 的執行由 Servlet 容器 FilterChain 完成,而攔截器通常通過動態代理的方式來執行。
  3. Filter 的生命週期由 Servlet 容器管理,而攔截器則可以通過 IoC (Inversion of Control) 容器來管理,因此可以通過注入等方式來獲取其他 Bean 的實例,因此使用會更方便。

 

瞭解兩者差異後,接下來透過下列幾個步驟就可以輕易達到這個功能。

  • 在 gradle 中加入 com.googlecode.htmlcompressor 相依套件
compile("com.googlecode.htmlcompressor:htmlcompressor:1.5.2")

 

  • 建立一個 class : CharResponseWrapper.java
public class CharResponseWrapper extends HttpServletResponseWrapper {

 protected CharArrayWriter charWriter;
    protected PrintWriter writer;
    protected boolean getOutputStreamCalled;
    protected boolean getWriterCalled;

    public CharResponseWrapper(HttpServletResponse response) {
        super(response);

        charWriter = new CharArrayWriter();
    }

    public ServletOutputStream getOutputStream() throws IOException {
        if (getWriterCalled) {
            throw new IllegalStateException("getWriter already called");
        }

        getOutputStreamCalled = true;
        return super.getOutputStream();
    }

    public PrintWriter getWriter() throws IOException {
        if (writer != null) {
            return writer;
        }
        if (getOutputStreamCalled) {
            throw new IllegalStateException("getOutputStream already called");
        }
        getWriterCalled = true;
        writer = new PrintWriter(charWriter);
        return writer;
    }

    public String toString() {
        String s = null;

        if (writer != null) {
            s = charWriter.toString();
        }
        return s;
    }
}

 

  • 建立 javax.servlet.Filter : HtmlFilter.java ,並加入 annotation: @Component 來啟用此 Filter
@Component
public class HtmlFilter implements Filter {
 
 protected FilterConfig config;

 public void init(FilterConfig config) throws ServletException {
        this.config = config;
    }
 
 @Override
 public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
   throws IOException, ServletException {
  
  ServletResponse newResponse = response;
  
  if (request instanceof HttpServletRequest) {
            newResponse = new CharResponseWrapper((HttpServletResponse) response);
        }

        chain.doFilter(request, newResponse);

        if (newResponse instanceof CharResponseWrapper) {
            String text = newResponse.toString();
            if (text != null) {
                HtmlCompressor htmlCompressor = new HtmlCompressor();
                response.getWriter().write(htmlCompressor.compress(text));
            }
        }

 }

}

 

這樣就可以讓 HTML 在輸出時,經過篩選器 ( Filter ) 及利用 htmlcompressor 將空白給去除。

 

 

 

Copyright © All rights reserved. | Newsphere by AF themes.