過濾器是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>
最後,當啓動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