Tomcat深入淺出——Filter與Listener(五)

Meteor發表於2022-07-10

一、Filter過濾器

1.1 Filter過濾器的使用

  • 這是過濾器介面的方法
public interface Filter {
    default void init(FilterConfig filterConfig) throws ServletException {
    }

    void doFilter(ServletRequest var1, ServletResponse var2, FilterChain var3) throws IOException, ServletException;

    default void destroy() {
    }
}
  • 一般情況下我們都在過濾器中新增公共的程式碼
  • 例如我們經常設定字元編碼utf-8,為了減少重複的操作,我們直接在過濾器中設定即可。
@WebFilter("/*")
public class MyFilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        //在Filter物件第一次被建立的時候呼叫,並且只呼叫一次
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        //doFilter()只要使用者傳送一次請求,則執行一次,傳送N次,則執行N次。在這個方法中編寫過濾規則
        System.out.println("doFilter方法,前1");
        //解決跨域問題
        HttpServletResponse resp = (HttpServletResponse) servletResponse;
        resp.setHeader("Access-Control-Allow-Origin", "*");
        resp.setHeader("Access-Control-Allow-Headers", "*");
        resp.setHeader("Access-Control-Allow-Method", "*");

        //執行下一個過濾器,如果說下一個不是過濾器,則會執行servlet
        filterChain.doFilter(servletRequest,servletResponse);
        System.out.println("doFilter方法,後1");
    }


    @Override
    public void destroy() {
        //在Filter物件被釋放/銷燬之前呼叫,並且只呼叫一次
        System.out.println("destroy方法");
    }
}
  • init方法:在Filter物件第一次被建立的時候呼叫,並且只呼叫一次

  • doFilter方法:只要使用者傳送一次請求,則執行一次,傳送N次,則執行N次。在這個方法中編寫過濾規則

  • destroy方法:在Filter物件被釋放/銷燬之前呼叫,並且只呼叫一次

  • filterChain.doFilter(request, response);執行下一個過濾器,如果下一個不是過濾器,則執行Servlet

目標Servlet是否執行取決於兩個條件:

  • 過濾器中是否編寫了filterChain.doFilter(request, response);
  • 使用者發的請求路徑是否和Servlet的請求路徑一致

注意:

  • Filter的優先順序天生就比Servlet高
  • 使用@WebFilter的時候,Filter執行順序根據類名順序執行。
  • Filter的生命週期與Servlet一樣,但是Filter會在伺服器啟動的時候就預設建立物件,而Servlet卻需要配置才可以。
  • 如果在web.xml中配置兩個或者多個過濾器時,執行順序根據<filter-mapping>的先後。

1.2 Filter的責任鏈設計模式

  • 我們先來看一下兩個過濾器的執行過程是什麼樣的

  • Filter過濾器的doFilter方法,執行順序遵循的是棧結構,但是過濾器本身的生命週期就和佇列差不多吧。
  • 其實doFilter方法,就是一種責任鏈設計模式!
//模仿棧
//模仿Filter設計模式
//缺點:在編譯階段已經完全確定了呼叫關係
//如果想要改變呼叫順序,必須要修改java程式碼
//違背了OCP原則(開閉原則)
public class Test {
    public static void main(String[] args) {
        System.out.println("main方法執行");
        m1();
        System.out.println("main執行完畢");
    }
    public static void m1() {
        System.out.println("m1方法執行");
        m2();
        System.out.println("m1執行完畢");
    }
    public static void m2() {
        System.out.println("m2方法執行");
        m3();
        System.out.println("m2執行完畢");
    }
    public static void m3() {
        System.out.println("目標正在執行中");
    }
}

  • 這是執行的結果,是不是和Filter一樣~~~?

二、Listener監聽器

  • 監聽器顧名思義:起到了監聽的作用,我想大家在javaGUI部分也瞭解過吧。
  • 監聽器可以監測我們網站時時的線上人數等等
  • 監聽器加上@WebListener註解或者在web.xml中配置一下即可,並不需要我們程式設計師去呼叫
  • 下面是一個session監聽器
@WebListener
public class MyListener01 implements HttpSessionAttributeListener {

    //監聽session行為的監聽器
    @Override
    public void attributeAdded(HttpSessionBindingEvent se) {
        System.out.println("add");
    }

    @Override
    public void attributeRemoved(HttpSessionBindingEvent se) {
        System.out.println("removed");
    }

    @Override
    public void attributeReplaced(HttpSessionBindingEvent se) {
        System.out.println("replaced");
    }
}
  • 下面是監聽整個Servlet生命週期的監聽器
@WebListener
public class MyListener implements ServletContextListener {

    //監聽整個servlet生命週期的監聽器
    @Override
    public void contextInitialized(ServletContextEvent sce) {
        System.out.println("contextInitialized");
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        System.out.println("contextDestroyed");
    }
}
  • 感覺用途不是特別多,我瞭解的也比較少,就先介紹這麼多,感謝你的認真閱讀?

三、結尾

  • 對於Tomcat的Servlet內容就總結這麼多,若想深入學習等待後續更新。
  • 我將會繼續更新關於Java方向的學習知識,感興趣的小夥伴可以關注一下。
  • 文章寫得比較走心,用了很長時間,絕對不是copy過來的!
  • 尊重每一位學習知識的人,同時也尊重每一位分享知識的人。
  • ?你的點贊與關注,是我努力前行的無限動力。?

相關文章