1. 程式人生 > 其它 >Java併發43:併發集合系列-序章

Java併發43:併發集合系列-序章

1._Filter

JavaWeb三大元件(Servlet,Filter,Listener)之一;

與Servlet類似,用來攔截請求,不是用來處理請求的;WEB開發人員通過Filter技術,對web伺服器管理的所有web資源:例如Jsp, Servlet, 靜態圖片檔案或靜態 html 檔案等進行攔截,從而實現一些特殊的功能。例如實現URL級別的許可權訪問控制、過濾敏感詞彙、壓縮響應資訊等一些高階功能。

Servlet API中提供了一個Filter介面,開發web應用時,如果編寫的Java類實現了這個介面,則把這個java類稱之為過濾器Filter。

執行地位在Servlet之前,客戶端傳送請求時,會先經過Filter,再到達目標Servlet中;響應時,會根據執行流程再次反向執行Filter。可以解決多個Servlet共性程式碼的冗餘問題(例如:亂碼處理、登入驗證)

2._Filter的生命週期

init在伺服器啟動時會建立Filter例項,並且每個型別的Filter只建立一個例項,從此不再建立,在建立完Filter例項後,會馬上呼叫init()方法完成初始化工作,這個方法只會被執行一次;

doFilter:這個方法會在使用者每次訪問目標資源(web.xml檔案配置Filter的url-pattern中的路徑)時執行,如果需要“放行”,那麼需要呼叫FilterChain的doFilter(ServletRequest,ServletResponse)方法,如果不呼叫FilterChain的doFilter()方法,那麼目標資源將無法執行;

destroy

:伺服器會在建立Filter物件之後,把Filter放到快取中一直使用,通常不會銷燬它。一般會在伺服器關閉時銷燬Filter物件,在銷燬Filter物件之前,伺服器會呼叫Filter物件的destory()方法。

修改TestFilter的程式碼,進行測試

public class TestFilter implements Filter {
    public void init(FilterConfig config) throws ServletException {
        System.out.println("init...");
    }

    public void destroy() {
        System.out.println("destroy...");
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
        System.out.println("filter....");
        chain.doFilter(request, response);
    }
}

3._Filter的配置

Filter的配置和Servlet的配置類似,分為xml和註解兩種配置方式。

1,xml配置

注意和 servlet區分

<?xml version="1.0" encoding="UTF-8"?>
<web-app 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_3_1.xsd"
         version="3.1">
    <filter>
        <!-- filter的名字,必須和另一組標籤中的filter的名字一致 -->
        <filter-name>TestFilter</filter-name>
        <!-- filter的全類名 -->
        <filter-class>com.qfedu.filter.TestFilter</filter-class>
    </filter>
    <filter-mapping>
        <!-- filter的名字,必須和另一組標籤中的filter的名字一致 -->
        <filter-name>TestFilter</filter-name>
        <!-- 被filter攔截的資源 -->
        <url-pattern>/TestServlet</url-pattern>
    </filter-mapping>
</web-app>

2,註解配置

在自定義的Filter類上使用註解@WebFilter,註解常用屬性:

  • filterName:filter的名字;
  • value:過濾的目標資源的地址。

如果@WebFilter只寫了字串,這個字串Filter過濾目標資源的地址。

@WebFilter(filterName = "AFilter", value = "/AServlet")
public class AFilter implements Filter {
    public void init(FilterConfig config) throws ServletException {
    }

    public void destroy() {
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
        System.out.println("AFilter...");
        chain.doFilter(request, response);
    }
}

3,過濾器路徑

過濾器的過濾路徑通常有三種形式:

  • 精確過濾匹配 ,比如/index.jsp/myservlet1
  • 字尾過濾匹配,比如*.jsp*.html*.jpg
  • 萬用字元過濾匹配/*,表示攔截所有。注意過濾器不能使用/匹配,/aaa/bbb/*允許。

4,過濾器鏈

客戶端對伺服器請求之後,伺服器呼叫Servlet之前會執行一組過濾器(多個過濾器),那麼這組過濾器就稱為一條過濾器鏈。

每個過濾器實現某個特定的功能,當第一個Filter的doFilter方法被呼叫時,Web伺服器會建立一個代表Filter鏈的FilterChain物件傳遞給該方法。在doFilter方法中,開發人員如果呼叫了FilterChain物件的doFilter方法,則Web伺服器會檢查FilterChain物件中是否還有filter,如果有,則呼叫第2個filter,如果沒有,則呼叫目標資源。

5,過濾器優先順序

在一個Web應用中,可以開發編寫多個Filter,這些Filter組合起來稱之為一個Filter鏈。 優先順序:

  • 如果為註解的話,是按照類全名稱的字串順序決定作用順序;
  • 如果web.xml,按照 filter-mapping註冊順序,從上往下
  • web.xml配置高於註解方式;
  • 如果註解和web.xml同時配置,會建立多個過濾器物件,造成過濾多次。

關於“註解和web.xml同時配置,會建立多個過濾器物件,造成過濾多次”

4._ 使用

1,建立javaweb專案

2, 建立過濾器類

@WebFilter(filterName = "AFilter", value = "/AServlet")
public class AFilter implements Filter {
    public void init(FilterConfig config) throws ServletException {
    }

    public void destroy() {
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
        System.out.println("AFilter...");
        chain.doFilter(request, response);
    }
}

3,建立被過濾的類

@WebServlet(name = "AServlet", value = "/AServlet")
public class AServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("doGet...");
    }
}

啟動專案,訪問 http://localhost:8080/javaweb__01_war_exploded/AServlet,會先打印出"AFilter..."然後才會執行對應的類,打印出doGet...