1. 程式人生 > >第十九次課

第十九次課

什麼是過濾器

Servlet API中提供了一個Filter介面,開發web應用時,如果編寫的Java類實現了這個介面,則把這個java類稱之為過濾器Filter。通過Filter技術,開發人員可以實現使用者在訪問某個目標資源之前,對訪問的請求和響應進行攔截。簡單說,就是可以實現web容器對某資源的訪問前截獲進行相關的處理,還可以在某資源向web容器返回響應前進行截獲進行處理。

實現第一個Filter程式

建立MyServlet

@WebServlet("/MyServlet")
public class MyServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        PrintWriter out=response.getWriter();
        out.print("Hello MyServlet ");

    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        doPost(request,response);
    }
}

建立MyFilter

用配置檔案(web.xml)實現filter

1.先建立一個Filter類,該類要實現Filter介面 在idea中,點右鍵,新建Filter,輸入檔名MyFilter1 在這裡插入圖片描述

MyFilter1:

public class MyFilter1 implements Filter {
    public void destroy() {
        //過濾器物件在銷燬時自動呼叫,釋放資源
    }

    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        //用於攔截使用者的請求,如果和當前過濾器的攔截路徑匹配,該方法會被呼叫

        PrintWriter out=resp.getWriter();

        out.write("HelloMyFilter");
        chain.doFilter(req, resp);
    }

    public void init(FilterConfig config) throws ServletException {
        //過濾器物件在初始化時呼叫,可以配置一些初始化引數
    }

}

web.xml

<filter>
        <filter-name>MyFilter1</filter-name>
        <filter-class>filter.MyFilter1</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>MyFilter1</filter-name>
        <url-pattern>/MyServlet</url-pattern>
    </filter-mapping>

<filter>根元素用於註冊一個Filter

<filter-name>子元素用於設定Filter名稱

<filter-class>子元素用於設定Filter類的完整名稱

<filter-mapping>根元素用於設定一個過濾器所攔截的資源

<filter-name>子元素必須 與中的子元素相同。

<url-pattern>子元素用於匹配使用者請求的URL.例如”/MyServlet”,這個URL還可以使用萬用字元””來表示,例如:“.do”適用於所有 以”.do” 結尾的Servlet路徑。 執行http://localhost:8080/MyServlet 結果:HelloMyFilterHello MyServlet

用註解實現filter

@WebFilter("/MyServlet")
public class MyFilter2 implements Filter {
    public void destroy() {
        //過濾器物件在銷燬時自動呼叫,釋放資源
    }

    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        //用於攔截使用者的請求,如果和當前過濾器的攔截路徑匹配,該方法會被呼叫

        PrintWriter out=resp.getWriter();

        out.write("HelloMyFilter");
        chain.doFilter(req, resp);
    
    }

    public void init(FilterConfig config) throws ServletException {
        //過濾器物件在初始化時呼叫,可以配置一些初始化引數

    }

}

Filter對映

使用萬用字元“*”攔截使用者的所有請求

<url-pattern>子元素用於匹配使用者請求的URL.例如”/MyServlet”,這個URL還可以使用萬用字元””來表示,例如:“.do”適用於所有 以”.do” 結尾的Servlet路徑。在註解中修改

@WebFilter("*.do")
public class MyFilter2 implements Filter {
    public void destroy() {
        //過濾器物件在銷燬時自動呼叫,釋放資源
    }

    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        //用於攔截使用者的請求,如果和當前過濾器的攔截路徑匹配,該方法會被呼叫

        PrintWriter out=resp.getWriter();

        out.write("HelloMyFilter2");
      //  chain.doFilter(req, resp); 

    }

    public void init(FilterConfig config) throws ServletException {
        //過濾器物件在初始化時呼叫,可以配置一些初始化引數

    }

}

Filter鏈

在一個Web應用程式中可以註冊多個Filter程式,每個Filter程式都可以針對某一個URL進行攔截。如果多個Filter程式都對同一個URL進行攔截,那麼這些Filter就會組成一個Filter鏈(也叫過濾器鏈)。Filter鏈用FilterChain物件來表示,FilterChain物件中有一個doFilter()方法,該方法的作用就是讓Filter鏈上的當前過濾器允許,請求進入下一個Filter。 MyFilter01.java

public void doFilter(ServletRequest request,ServletResponse response, FilterChain chain) throws IOException, ServletException {

        //用於攔截使用者的請求,如果和當前過濾器的攔截路徑匹配,該方法會被呼叫

        PrintWriterout=response.getWriter();

        out.write("HelloMyFilter01<br/>");

        chain.doFilter(request,response);

    }

MyFilter02.java

 public void doFilter(ServletRequest request,ServletResponse response, FilterChain chain) throws IOException, ServletException {

        //用於攔截使用者的請求,如果和當前過濾器的攔截路徑匹配,該方法會被呼叫

        PrintWriterout=response.getWriter();

        out.write("MyFilter02 Before<br/>");

        chain.doFilter(request,response);

        out.write("MyFilter02 After<br/>");

    }

Web.xml

<filter>

    <display-name>MyFilter01</display-name>

    <filter-name>MyFilter01</filter-name>

    <filter-class>cn.lctvu.filter.MyFilter01</filter-class>

 </filter>

 <filter-mapping>

    <filter-name>MyFilter01</filter-name>

    <url-pattern>/MyServlet</url-pattern>

 </filter-mapping>

 <filter>

    <display-name>MyFilter02</display-name>

    <filter-name>MyFilter02</filter-name>

    <filter-class>cn.lctvu.filter.MyFilter02</filter-class>

 </filter>

 <filter-mapping>

    <filter-name>MyFilter02</filter-name>

    <url-pattern>/MyServlet</url-pattern>

  </filter-mapping>

注意:Filter鏈中各個Filter的攔截順序與它們在Web.xml檔案中元素的對映順序一致,由於MyFilter01的元素位於MyFilter02的元素前面,因此使用者的訪問請求首先會被MyFilter01攔截,然後再被MyFilter02攔截。

在3.0之後新增@WebFilter註解,當使用註解配置多個Filter時,使用者無法控制其執行順序,此時Filter過濾的順序是按照Filter的類名來控制的,按自然排序的規則。

FilterConfig介面

為了獲取Filter程式在web.xml檔案中的配置資訊,Servlet API提供了一個FilterConfig介面,該介面封裝了Filter程式在web.xml中的所有註冊資訊,並且提供了一系列獲取這些配置資訊的方法。 MyFilter03

public class MyFilter03 implements Filter {
    private String characterEncoding;

    FilterConfig fc;
    public void destroy() {
    }

    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        // 輸出引數資訊

        characterEncoding=fc.getInitParameter("encoding");

        System.out.println("encoding初始化引數值:"+characterEncoding);
        chain.doFilter(req, resp);
    }

    public void init(FilterConfig config) throws ServletException {
        this.fc=config;

    }

}