過濾器導圖詳解


過濾器是web開發中常用的開發方式,比如一些典型的應用場景:

用戶身份認證、對用戶請求進行記錄和審核、對用戶發送的數據進行替換和過濾、轉換圖像格式、對響應內容壓縮、加密請求或響應等等。

本篇就了解下監聽器的主要使用方法。

 

什么是過濾器?

  過濾器的生命周期

  過濾器的生命周期與web容器相同,當web容器啟動時,就會讀取應用的web.xml配置文件,如果這里配置了過濾器,容器就會執行實例化,並調用過濾器的init方法。

  之后用戶的每一次請求都會執行過濾器的doFilter方法。

  當web容器銷毀時,就會執行destroy方法,釋放資源。

  過濾器的執行過程

  過濾器看名字就能知道大概的用法,它就像一個篩子,可以篩選特定的數據或請求。執行過程如下圖所示:

  用戶在發送請求后,如果該請求滿足過濾器的過濾規則,web容器就會執行過濾器中的doFilter方法進行特定的操作;然后通過調用FilterChain.doFilter轉交給web容器。web容器執行完成后把資源返回給過濾器,再展現給用戶。

 

簡單的過濾器實例

  下面通過一個簡單的代碼,看看過濾器的編寫。

  首先,需要創建一個過濾器,過濾器集成javax.servlet.Filter接口,其中必須實現三個方法:init() doFilter() destroy()

public class MyFilter implements Filter{
    public void destroy() {
        System.out.println("MyFilter destroy");
    }
    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException {
        System.out.println("MyFilter start...dofilter");
        chain.doFilter(request, response);//對請求放行
        System.out.println("MyFilter end...dofilter");
    }
    public void init(FilterConfig arg0) throws ServletException {
        System.out.println("MyFilter init");
    }
}

  init()方法是在web容器實例化過濾器時調用的。

  doFilter()方法是每次有請求,且滿足過濾規則時調用。

  destroy()方法是web容器關閉時,調用。

 

  然后,在web.xml中配置相應的選項。如果是servlet3.0,那么支持注解的方式配置過濾器。

<filter>
      <filter-name>MyFilter</filter-name>
      <filter-class>com.test.filter.MyFilter</filter-class>
</filter>
<filter-mapping>
      <filter-name>MyFilter</filter-name>
      <url-pattern>/index.jsp</url-pattern>
        <!--<dispatcher></dispatcher>-->
</filter-mapping>

  其中幾個必備的項:

  在<filter>中配置了過濾器,filter-name是過濾器的名字,filter-class是過濾器的類;

  在<filter-mapping>中配置了過濾器的映射規則,filter-name是過濾器的名字,url-pattern是過濾的規則,dispatcher是過濾器的分類(主要包括四種,稍后講解)

  這里先說下過濾器的規則,如果想要全部的請求都過濾,那么可以寫/*

  如果想要過濾index.jsp  index.html 可以寫/index*

  如果只想過濾index.jsp,可以寫成/index.jsp

 

  其次,配置好后,創建index.jsp

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
    This is Filter JSP!
    <%
        System.out.println("index jsp");
    %>
</body>
</html>
View Code

  

  最后,當啟動web容器后,可以在控制台中發現,初始化時,執行了init方法

  訪問對應的web資源,可以看到控制台按照執行的順序打印消息:

多個過濾器操作

  多個過濾器執行與上面差不多。

  在上面代碼的基礎上,再增加一個過濾器:

public class SecondFilter implements Filter{
    public void destroy() {
        System.out.println("SecondFilter destroy()");
    }
    public void doFilter(ServletRequest arg0, ServletResponse arg1,
            FilterChain chain) throws IOException, ServletException {
        System.out.println("SecondFilter doFilter start");
        chain.doFilter(arg0, arg1);
        System.out.println("SecondFilter doFilter end");
    }

    public void init(FilterConfig arg0) throws ServletException {
        System.out.println("SecondFilter init()");
    }
}

  在web.xml中增加過濾器配置

  <filter>
      <filter-name>SecondFilter</filter-name>
      <filter-class>com.test.filter.SecondFilter</filter-class>
  </filter>
  <filter-mapping>
      <filter-name>SecondFilter</filter-name>
      <url-pattern>/index.jsp</url-pattern>
  </filter-mapping>

  啟動web容器,控制台輸出init信息

  訪問頁面,可以看到由於在web.xml中映射配置MyFilter在SecondFilter上面,

  因此輸出如下消息:

 

  類似的,如果把SecondFilter配置放在上面,就會先執行SecondFilter的doFilter方法。

過濾器的分類

  最后看一下過濾器的分類,過濾器主要包括四種,REQUEST\FORWARD\INCLUDE\ERROR(3.0額外新增了一個異步請求ASYNC)。

  上面的過濾器都是采用REQUEST的方式,直接請求。由於沒有配置dispathcer,默認就會按照REQUEST的方式進行

  直接看一下FORWARD的使用方法,在doFilter中執行下面的方法:

public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException {
        System.out.println("MyFilter start...dofilter");
        HttpServletRequest req = (HttpServletRequest)request;
        req.getRequestDispatcher("main.jsp").forward(request, response);
        System.out.println("MyFilter end...dofilter");
}

  此時頁面請求就會直接跳轉到main.jsp,觸發FORWARD類型過濾器,過濾器配置選項如下:

  <filter>
      <filter-name>MyFilter</filter-name>
      <filter-class>com.test.filter.MyFilter</filter-class>
  </filter>
  <filter-mapping>
      <filter-name>MyFilter</filter-name>
      <url-pattern>/index.jsp</url-pattern>
  </filter-mapping>
  <filter>
      <filter-name>SecondFilter</filter-name>
      <filter-class>com.test.filter.SecondFilter</filter-class>
  </filter>
<!--     <filter-mapping>
      <filter-name>SecondFilter</filter-name>
      <url-pattern>/index.jsp</url-pattern>
  </filter-mapping> -->
  <filter-mapping>
      <filter-name>SecondFilter</filter-name>
      <url-pattern>/main.jsp</url-pattern>
      <dispatcher>FORWARD</dispatcher>
  </filter-mapping>

  啟動后發現,原本請求Index.jsp跳轉到了main.jsp。

  此時,如果第二個過濾器采用的是REQUEST,就不會觸發了。

  另外,還可以使用JSP頁面標簽,執行跳轉,此時過濾器也可以觸發。比如在JSP頁面中添加<jsp:forward>標簽

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>

<jsp:forward page="/main.jsp"></jsp:forward>

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> <title>Insert title here</title> </head> <body> </body> </html>

  INCLUDE與FORWARD類似,使用方法也相同,只是名字不同而已,就不做過多的介紹了。

  然后看一下ERROR過濾器,通常我們會在web.xml中配置錯誤頁面,如下:

<error-page>
      <error-code>404</error-code>
    <location>/error.jsp</location>
  </error-page>

  此時,如果訪問不存在的頁面,http://localhost:8080/xxx.jsp就會跳轉到error.jsp

  此時如果過濾器通過REQUEST方式,想要觸發,url填寫的是/error.jsp並不會起作用,此時就需要把dispathcer改成 ERROR,並且放置在error-page標簽下面:

  <error-page>
      <error-code>404</error-code>
    <location>/error.jsp</location>
  </error-page>
  <!-- 需要放在errorpage下面 -->
  <filter>
      <filter-name>ErrorFilter</filter-name>
      <filter-class>com.test.filter.ErrorFilter</filter-class>
  </filter> 
  <filter-mapping>
      <filter-name>ErrorFilter</filter-name>
      <url-pattern>/error.jsp</url-pattern>
      <dispatcher>ERROR</dispatcher>
  </filter-mapping>

  這樣就會觸發ERROR過濾器了。

參考

【1】過濾器的應用:http://www.ylzx8.cn/web/web/979338.html

【2】過濾器視頻教程:http://www.imooc.com/learn/213


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM