初探 Servlet Filter

有沒有發現我們前幾週的專案進度有個大 Bug!就是我們的程式中,幾乎沒有任何的例外判斷…
為什麼呢?
就是因為我們這週的標題
Filter
我打算把 Servlet 所有的例外處理都交給 Filter 來過濾,不過這週先不會直接把 Filter 用進專案,我們還是要先教會大家什麼是 Fliter 吧!
開始吧!!


Filter (過濾器)

先來看幾個最簡單的 Filter 吧!

// AllPatternFilter.java
@WebFilter("/*")
public class AllPatternFilter extends HttpFilter {
    @Override
    protected void doFilter(HttpServletRequest req, HttpServletResponse res, FilterChain chain) throws IOException, ServletException {
        System.out.println("任何 Servlet 請求都會經過我");
        chain.doFilter(req, res); // 記得 FilterChain 的 doFilter() 方法要呼叫,才會往下走
    }
}
// HelloWorldFilter.java
@WebFilter(
    urlPatterns = {"/hello-world"}
)
public class HelloWorldFilter extends HttpFilter {
    @Override
    protected void doFilter(HttpServletRequest req, HttpServletResponse res, FilterChain chain) throws IOException, ServletException {
        System.out.println("/hello-world 的請求都會經過我");
        chain.doFilter(req, res); // 記得 FilterChain 的 doFilter() 方法要呼叫,才會往下走
    }
}

Filter 過濾器的使用其實跟 Servlet 很像,
粗淺瞭解它的話
一樣是繼承 一個類別、覆寫掉方法、定義 urlPattern …
我也是這樣瞭解的,不過就是有些細節要注意就是

首先!基本的 @WebFilter() 的設定請幫我看
Servlet 使用教戰守則 – Annotation 篇
的 @WebFilter 片段

透過 @WebFilter() 我們可以定義我們 Filter 的
Filter 名稱、url 匹配規則 等等的…
很豐富,我們之後的文章會詳細介紹到
我們在最一開始只要會用 urlPatterns 就好了

可以看到第一個寫的是 /*
這就代表我們任何的請求都會經過 AllPatternFilter.java 這層 Filter

而第二個是 /hello-world
這也就是指定 /hello-world 這個 url 會經過 HelloWorldFilter.java 這層 Filter

而且實際上 /hello-world
是會經過 HelloWorldFilter.java 跟 AllPatternFilter.java 這兩層 Filter 的
順序是這樣的

// /hello-world 的請求都會經過我
// 任何 Servlet 請求都會經過我

如果要能夠客製化順序的話,目前我找到的解決方法只有使用 web.xml 來定義了!
可能匹配規則就不能完全用 Annotation 來寫了這樣

這一篇比較亂一點… 就先附上目錄結構吧!

├── src
│   ├── main
│   │   ├── java
│   │   │   └── com
│   │   │       └── judysocute
│   │   │           ├── AllPatternFilter.java
│   │   │           ├── HelloWorld.java
│   │   │           └── HelloWorldFilter.java
│   │   ├── resources
│   │   └── webapp
│   │       └── WEB-INF
│   │           └── web.xml

我們先把我們 Filter 的 Annotation 都拿掉

// AllPatternFilter.java
public class AllPatternFilter extends HttpFilter {
    @Override
    protected void doFilter(HttpServletRequest req, HttpServletResponse res, FilterChain chain) throws IOException, ServletException {
        System.out.println("任何 Servlet 請求都會經過我");
        chain.doFilter(req, res); // 記得 FilterChain 的 doFilter() 方法要呼叫,才會往下走
    }
}
// HelloWorldFilter.java
@WebFilter(
    urlPatterns = {"/hello-world"}
)
public class HelloWorldFilter extends HttpFilter {
    @Override
    protected void doFilter(HttpServletRequest req, HttpServletResponse res, FilterChain chain) throws IOException, ServletException {
        System.out.println("/hello-world 的請求都會經過我");
        chain.doFilter(req, res); // 記得 FilterChain 的 doFilter() 方法要呼叫,才會往下走
    }
}

只留這樣,再來在 web.xml 定義內容

<!--  web.xml  -->
<web-app version="4.0"
         xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
         http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd">
    <filter>
        <filter-name>AllPattern</filter-name>
        <filter-class>com.judysocute.AllPatternFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>AllPattern</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <filter>
        <filter-name>HelloWorld</filter-name>
        <filter-class>com.judysocute.HelloWorldFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>HelloWorld</filter-name>
        <url-pattern>/hello-world</url-pattern>
    </filter-mapping>
</web-app>

Filter 的先後順序會依據 web.xml 內定義的順序

畢竟只是初探,下一篇會更仔細介紹的!

Leave a Reply