過濾器導圖詳解

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

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

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

 

什麼是過濾器?

  過濾器的生命週期app

  過濾器的生命週期與web容器相同,當web容器啓動時,就會讀取應用的web.xml配置文件,若是這裏配置了過濾器,容器就會執行實例化,並調用過濾器的init方法。異步

  以後用戶的每一次請求都會執行過濾器的doFilter方法。jsp

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

  過濾器的執行過程ui

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

  用戶在發送請求後,若是該請求知足過濾器的過濾規則,web容器就會執行過濾器中的doFilter方法進行特定的操做;而後經過調用FilterChain.doFilter轉交給web容器。web容器執行完成後把資源返回給過濾器,再展示給用戶。url

 

簡單的過濾器實例

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

  首先,須要建立一個過濾器,過濾器集成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

相關文章
相關標籤/搜索