WEB過濾器是一個服務器端的組件,它可以截取用戶端的請求與相應信息,并對這些信息過濾。
過濾器的工作原理和生命周期在沒有Web過濾器的情況下,用戶直接訪問服務器上的Web資源。但是如果存在過濾器,用戶就不可以直接訪問過濾器了。
Web容器啟動的時候過濾器就已經啟動了,用戶的請求到達過濾器,過濾器判斷用戶的請求是否符合過濾規則,如果符合規則則將用戶的請求發送給Web資源,Web資源將響應信息發送給過濾器,過濾器將Web資源的響應發送給用戶。工作原理如下圖所示:
過濾器的生命周期:
其中實例化方法在Web容器開始裝載的時候就執行,初始化方法配置一些初始化參數,Web容器卸載(服務器關閉)的時候執行銷毀方法。過濾方法會執行多次,其他方法只會執行一次。
第一個過濾器1.創建一個類實現javax.servlet.Filter接口。需要實現該接口中的3個方法。
1 package filter; 2 3 import java.io.IOException; 4 5 import javax.servlet.Filter; 6 import javax.servlet.FilterChain; 7 import javax.servlet.FilterConfig; 8 import javax.servlet.ServletException; 9 import javax.servlet.ServletRequest;10 import javax.servlet.ServletResponse;11 12 public class FirstFilter implements Filter {13 14 public void destroy() {15 System.out.FirstFilter.java
- init(FilterConfig):過濾器的初始化方法,Web容器創建過濾器之后將調用這個方法,在這個方法中可以讀取web.xml中的過濾器參數。
- doFilter(ServletRequest,ServletResponse,FilterChain):完成實際的過濾操作,是過濾器的核心方法。當用戶請求訪問與過濾器相關聯的URL的時候,Web容器將先調用過濾器的doFilter方法。FilterChain參數可以調用chain.doFilter方法【放行方法】,將請求傳送給下一個過濾器(或者目標資源),或利用轉發、重定向將請求轉發給其他資源。
- destroy():Web容器在銷毀過濾器實例前調用該方法,在這個方法中可以釋放過濾器占用的資源?!敬蠖鄶登闆r下用不到】
2.在web.xml中配置過濾器(和再web.xml中注冊servlet類似)
在MyEclipse中提供了可視化的配置web.xml,如下圖:
1 <?xml version="1.0" encoding="UTF-8"?> 2 <web-app version="2.5" 3 xmlns="http://java.sun.com/xml/ns/javaee" 4 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 5 xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 6 http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> 7 <display-name></display-name> 8 <welcome-file-list> 9 <welcome-file>index.jsp</welcome-file>10 </welcome-file-list>11 12 <!-- 配置過濾器開始 -->13 <filter>14 <filter-name>FirstFilter</filter-name>15 <filter-class>filter.FirstFilter</filter-class>16 </filter>17 <filter-mapping>18 <filter-name>FirstFilter</filter-name>19 <url-pattern>/*</url-pattern>20 </filter-mapping>21 <!-- 配置過濾器結束 -->22 23 </web-app>web.xml在index.jsp中我們在控制臺打印一行信息:"**********這是index.jsp*********";
將項目部署到服務器,啟動服務器:
在Servlet容器裝載的時候,執行過濾器的init方法,當用戶請求頁面的時候首先執行doFilter()方法,當Servlet容器卸載的時候執行過濾器的銷毀方法?!咀⒁猓河脩舻恼埱笙仁堑竭_過濾器并不是直接訪問的Web資源】
還有一點需要注意:用戶雖然能夠改變用戶請求的資源(例如:網上購物的時候點擊“立即購買”,這個請求先要到達過濾器,如果過濾器檢測到用戶沒有登錄,就會將頁面重定向到登陸頁),但是過濾器不能直接處理用戶的請求(過濾器不是Servlet),不能直接返回數據。
過濾器鏈針對同一個用戶請求(url-pattern),與之匹配的過濾器有多個,這個時候用戶請求就會依次通過各個過濾器到達web資源。
新建2個過濾器:
1 package filter; 2 3 import java.io.IOException; 4 5 import javax.servlet.Filter; 6 import javax.servlet.FilterChain; 7 import javax.servlet.FilterConfig; 8 import javax.servlet.ServletException; 9 import javax.servlet.ServletRequest;10 import javax.servlet.ServletResponse;11 12 public class FirstFilter implements Filter {13 14 public void destroy() {15 System.out.println("*********過濾器1----->銷毀方法*******");16 17 }18 19 public void doFilter(ServletRequest request, ServletResponse response,20 FilterChain filterChain) throws IOException, ServletException {21 System.out.println("*******開始執行過濾器1----->doFilter方法*********");22 filterChain.doFilter(request, response);23 System.out.println("*******結束執行過濾器1----->doFilter方法**********");24 }25 26 public void init(FilterConfig arg0) throws ServletException {27 System.out.println("*******執行過濾器1------>初始化方法***********");28 29 }30 31 }FirstFilter.java1 package filter; 2 3 import java.io.IOException; 4 5 import javax.servlet.Filter; 6 import javax.servlet.FilterChain; 7 import javax.servlet.FilterConfig; 8 import javax.servlet.ServletException; 9 import javax.servlet.ServletRequest;10 import javax.servlet.ServletResponse;11 12 public class SecondFilter implements Filter {13 14 public void destroy() {15 System.out.println("*********過濾器2----->銷毀方法*******");16 }17 18 public void doFilter(ServletRequest request, ServletResponse response,19 FilterChain filterChain) throws IOException, ServletException {20 System.out.println("*******開始執行過濾器2----->doFilter方法*********");21 filterChain.doFilter(request, response);22 System.out.println("*******結束執行過濾器2----->doFilter方法**********");23 }24 25 public void init(FilterConfig arg0) throws ServletException {26 System.out.println("*******執行過濾器2------>初始化方法***********");27 }28 29 }SecondFilter.java在web.xml中配置兩個過濾器(第一個過濾器在前面,兩個過濾器都匹配index.jsp)
1 <?xml version="1.0" encoding="UTF-8"?> 2 <web-app version="2.5" 3 xmlns="http://java.sun.com/xml/ns/javaee" 4 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 5 xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 6 http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> 7 <display-name></display-name> 8 <welcome-file-list> 9 <welcome-file>index.jsp</welcome-file>10 </welcome-file-list>11 12 <!-- 配置過濾器開始 -->13 <!-- 過濾器1 -->14 <filter>15 <filter-name>FirstFilter</filter-name>16 <filter-class>filter.FirstFilter</filter-class>17 </filter>18 <filter-mapping>19 <filter-name>FirstFilter</filter-name>20 <url-pattern>/index.jsp</url-pattern>21 </filter-mapping>22 <!-- 過濾器2 --> 23 <filter>24 <filter-name>SecondFilter</filter-name>25 <filter-class>filter.SecondFilter</filter-class>26 </filter>27 <filter-mapping>28 <filter-name>SecondFilter</filter-name>29 <url-pattern>/index.jsp</url-pattern>30 </filter-mapping>31 <!-- 配置過濾器結束 -->32 33 </web-app>web.xml在index.jsp中我們打印如下的一句話:System.out.println("******** 這是index.jsp,處理過程完成 *********");
運行結果:
過濾器的分類:
Servlet 2.5中將過濾器分為4種,如下圖所示:
1.REQUEST過濾器
新建一個過濾器FirstFilter(在web.xml中配置兩個過濾地址index.jsp和main.jsp):
1 <?xml version="1.0" encoding="UTF-8"?> 2 <web-app version="2.5" 3 xmlns="http://java.sun.com/xml/ns/javaee" 4 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 5 xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 6 http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> 7 <display-name></display-name> 8 <welcome-file-list> 9 <welcome-file>index.jsp</welcome-file>10 </welcome-file-list>11 12 <!-- 配置過濾器開始 -->13 <filter>14 <filter-name>FirstFilter</filter-name>15 <filter-class>filter.FirstFilter</filter-class>16 </filter>17 <filter-mapping>18 <filter-name>FirstFilter</filter-name>19 <url-pattern>/index.jsp</url-pattern>20 <dispatcher>REQUEST</dispatcher>21 </filter-mapping>22 <filter-mapping>23 <filter-name>FirstFilter</filter-name>24 <url-pattern>/main.jsp</url-pattern>25 <dispatcher>REQUEST</dispatcher>26 </filter-mapping>27 <!-- 配置過濾器結束 -->28 29 </web-app>web.xml在FirstFilter的doFilter方法中將頁面重定向到main.jsp
1 package filter; 2 3 import java.io.IOException; 4 5 import javax.servlet.Filter; 6 import javax.servlet.FilterChain; 7 import javax.servlet.FilterConfig; 8 import javax.servlet.ServletException; 9 import javax.servlet.ServletRequest;10 import javax.servlet.ServletResponse;11 import javax.servlet.http.HttpServletRequest;12 import javax.servlet.http.HttpServletResponse;13 14 public class FirstFilter implements Filter {15 16 public void destroy() {17 System.out.println("*********過濾器1----->銷毀方法*******");18 19 }20 21 public void doFilter(ServletRequest request, ServletResponse response,22 FilterChain filterChain) throws IOException, ServletException {23 24 HttpServletRequest req = (HttpServletRequest) request;25 HttpServletResponse res = (HttpServletResponse) response;26 27 System.out.println("*******開始執行過濾器1----->doFilter方法*********");28 res.sendRedirect(req.getContextPath() + "/main.jsp");//重定向29 System.out.println("*******結束執行過濾器1----->doFilter方法**********");30 }31 32 public void init(FilterConfig arg0) throws ServletException {33 System.out.println("*******執行過濾器1------>初始化方法***********");34 35 }36 37 }FirstFilter.java啟動服務器:
當我們訪問index.jsp的時候,過濾器將頁面重定向到main.jsp——相當于我們又重新請求了main.jsp,main.jsp又會遇到過濾器,如此頁面不停重定向到main.jsp,產生了死循環不會輸出任何內容!
換一種方式,我們在過濾器中使用服務器內部轉發的方式將頁面轉發到main.jsp(main.jsp向頁面打印"這是main.jsp")。
1 package filter; 2 3 import java.io.IOException; 4 5 import javax.servlet.Filter; 6 import javax.servlet.FilterChain; 7 import javax.servlet.FilterConfig; 8 import javax.servlet.ServletException; 9 import javax.servlet.ServletRequest;10 import javax.servlet.ServletResponse;11 import javax.servlet.http.HttpServletRequest;12 import javax.servlet.http.HttpServletResponse;13 14 public class FirstFilter implements Filter {15 16 public void destroy() {17 System.out.println("*********過濾器1----->銷毀方法*******");18 19 }20 21 public void doFilter(ServletRequest request, ServletResponse response,22 FilterChain filterChain) throws IOException, ServletException {23 24 HttpServletRequest req = (HttpServletRequest) request;25 HttpServletResponse res = (HttpServletResponse) response;26 27 System.out.println("*******開始執行過濾器1----->doFilter方法*********");28 req.getRequestDispatcher("main.jsp").forward(request, response);//使用服務器內部轉發29 System.out.println("*******結束執行過濾器1----->doFilter方法**********");30 }31 32 public void init(FilterConfig arg0) throws ServletException {33 System.out.println("*******執行過濾器1------>初始化方法***********");34 35 }36 37 }FirstFilter.java運行結果:
2.FORWARD過濾器
將main.jsp的過濾規則改為FORWARD。
1 …… 2 <filter-mapping>3 <filter-name>FirstFilter</filter-name>4 <url-pattern>/main.jsp</url-pattern>5 <dispatcher>FORWARD</dispatcher>6 </filter-mapping>7 ……重新訪問index.jsp
3.INCLUDE過濾器
INCLUDE和FORWARD過濾器的使用類似,對應的jsp動作是include。
4.ERROR過濾器
例如我們訪問一個錯誤的頁面時,系統會給出一個錯誤,用戶看不懂這個錯誤是什么概念——我們需要給出一些人性化的提示。
以下是沒有在web.xml中配置錯誤頁,用戶訪問一個不存在的頁面:
在web.xml中配置錯誤頁:
1 <?xml version="1.0" encoding="UTF-8"?> 2 <web-app version="2.5" 3 xmlns="http://java.sun.com/xml/ns/javaee" 4 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 5 xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 6 http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> 7 <display-name></display-name> 8 <welcome-file-list> 9 <welcome-file>index.jsp</welcome-file>10 </welcome-file-list>11 12 <!-- 配置錯誤頁面 -->13 <error-page>14 <error-code>404</error-code>15 <location>/error.jsp</location>16 </error-page>17 18 </web-app>web.xml在web.xml中配置404錯誤的頁面為error.jsp則當用戶訪問一個不存在的頁面時將會將error.jsp中的內容輸出(以人性化的方式提示用戶):
當頁面出現錯誤或者異常的時候,ERROR過濾器可以將錯誤或者異常捕捉到,系統會記錄下錯誤的信息,程序員就可以查找錯誤的來源。
新建一個ErrorFilter,并在web.xml中進行如下配置:
1 <!-- 配置錯誤頁面 --> 2 <error-page> 3 <error-code>404</error-code> 4 <location>/error.jsp</location> 5 </error-page> 6 …… 7 <filter> 8 <filter-name>ErrorFilter</filter-name> 9 <filter-class>filter.ErrorFilter</filter-class>10 </filter>11 <filter-mapping>12 <filter-name>ErrorFilter</filter-name>13 <url-pattern>/error.jsp</url-pattern>14 <dispatcher>ERROR</dispatcher>15 </filter-mapping>16 ……web.xml錯誤過濾器ErrorFilter
1 package filter; 2 3 import java.io.IOException; 4 5 import javax.servlet.Filter; 6 import javax.servlet.FilterChain; 7 import javax.servlet.FilterConfig; 8 import javax.servlet.ServletException; 9 import javax.servlet.ServletRequest;10 import javax.servlet.ServletResponse;11 12 public class ErrorFilter implements Filter {13 14 public void destroy() {15 16 }17 18 public void doFilter(ServletRequest request, ServletResponse response,19 FilterChain filterChain) throws IOException, ServletException {20 System.out.println("檢測到錯誤信息!");21 filterChain.doFilter(request, response);//注意打印錯誤后要放行,不然頁面不會顯示22 }23 24 public void init(FilterConfig filterConfig) throws ServletException {25 26 }27 28 }ErrorFilter.java
J2EE5默認的web.xml是Servlet 2.5,J2EE6默認的web.xml是Servlet 3.0【支持異步處理】。
異步處理:如果在過濾器的doFilter()方法中頁面跳轉到了一個Servlet用于業務的處理,加入Servlet處理的業務時間花費很多,這時過濾器就會一直等待Servlet執行完成。這樣用戶體驗就會非常差。Servlet 3.0支持異步處理。
在Servlet中新加入了@WebFilter Annotation。該Annotation用于將一個類聲明為過濾器,該注解將會在部署時被容器處理,容器將根據具體的屬性配置相應的類,將響應的類部署為過濾器。——因此我們不需要在web.xml中配置過濾器,只需要用注解的方式。@WebFilter的常用屬性如下:
下面使用J2EE6.0創建一個Web項目,創建一個過濾器名稱為AsyncFilter,使用@WebFilter Annotation配置該過濾器(PS:可以不再web.xml中注冊該過濾器):
1 package filter; 2 3 import java.io.IOException; 4 5 import javax.servlet.DispatcherType; 6 import javax.servlet.Filter; 7 import javax.servlet.FilterChain; 8 import javax.servlet.FilterConfig; 9 import javax.servlet.ServletException;10 import javax.servlet.ServletRequest;11 import javax.servlet.ServletResponse;12 import javax.servlet.annotation.WebFilter;13 14 @WebFilter(filterName = "AsyncFilter", value = { "/servlet/AsyncServlet" }, asyncSupported = true, dispatcherTypes = {15 DispatcherType.ASYNC, DispatcherType.REQUEST })16 public class AsyncFilter implements Filter {17 18 @Override19 public void destroy() {20 System.out.println("***** 銷毀AsyncFilter *****");21 }22 23 @Override24 public void doFilter(ServletRequest request, ServletResponse response,25 FilterChain filterChain) throws IOException, ServletException {26 System.out.println("***** 開始AsyncFilter *****");27 filterChain.doFilter(request, response);//放行28 System.out.println("***** 結束AsyncFilter *****");29 }30 31 @Override32 public void init(FilterConfig filterConfig) throws ServletException {33 System.out.println("***** 初始化AsyncFilter *****");34 }35 36 }AsyncFilter.java創建一個處理業務的Servlet(該Servlet在doGet方法中使用了線程的休眠方法休眠了10s模擬業務的花費時間)
1 package servlet; 2 3 import java.io.IOException; 4 import java.util.Date; 5 6 import javax.servlet.AsyncContext; 7 import javax.servlet.ServletException; 8 import javax.servlet.http.HttpServlet; 9 import javax.servlet.http.HttpServletRequest;10 import javax.servlet.http.HttpServletResponse;11 12 public class AsyncServlet extends HttpServlet {13 14 public class Excutor implements Runnable{15 private AsyncContext context;16 public Excutor(AsyncContext context) {17 this.context = context;18 }19 20 @Override21 public void run() {22 // 執行相關的復雜業務23 try {24 Thread.sleep(1000*10);//休眠10s25 // context.getRequest();26 // context.getResponse();27 System.out.println("業務完成執行時間:"+new Date());28 } catch (InterruptedException e) {29 e.printStackTrace();30 }31 }32 33 }34 35 public AsyncServlet() {36 super();37 }38 39 public void destroy() {40 super.destroy(); // Just puts "destroy" string in log41 }42 43 public void doGet(HttpServletRequest request, HttpServletResponse response)44 throws ServletException, IOException {45 46 AsyncContext context = request.startAsync(); //HttpServletRequest對象開始異步方法47 // context.getRequest();48 // context.getResponse();49 50 System.out.println("Servlet執行開始時間:"+new Date());51 new Thread(new Excutor(context)).start();52 request.getRequestDispatcher("/index.jsp").forward(request, response);53 System.out.println("Servlet執行結束時間:"+new Date());54 }55 56 public void doPost(HttpServletRequest request, HttpServletResponse response)57 throws ServletException, IOException {58 59 doGet(request, response);60 }61 62 public void init() throws ServletException {63 64 }65 66 }AsyncServlet.java編寫好異步處理業務的Servlet類之后一定要在web.xml中配置該Servlet啟用異步,如下圖所示:
在index.jsp中有一個鏈接指向AsyncServlet:
<a href="<%=request.getContextPath() %>/servlet/AsyncServlet">點擊跳轉到AsyncServlet處理業務</a>運行結果:
過濾器在實際項目中的應用場景
用戶身份的驗證
例如現在有一個web項目,登陸頁login.jsp將用戶名和密碼提交給LoginServlet處理,Servlet使用request.getParameter方法獲得表單中的用戶名和密碼,將用戶名和密碼進行驗證,驗證成功則頁面重定向到success.jsp,顯示登陸成功和登錄的用戶名【保存在session中再從session中取出】;如果登錄失敗則重定向到failure.jsp。
在不使用過濾器的情況下,即使用戶不進行登錄也可以訪問到success.jsp——任何人都可以訪問到success.jsp,這顯然來說不安全。
驗證用戶身份的Servlet(驗證用戶名和密碼都是admin):
1 package servlet; 2 3 import java.io.IOException; 4 5 import javax.servlet.ServletException; 6 import javax.servlet.http.HttpServlet; 7 import javax.servlet.http.HttpServletRequest; 8 import javax.servlet.http.HttpServletResponse; 9 import javax.servlet.http.HttpSession;10 11 public class LoginServlet extends HttpServlet {12 13 public LoginServlet() {14 super();15 }16 17 public void destroy() {18 super.destroy(); // Just puts "destroy" string in log19 }20 21 public void doPost(HttpServletRequest request, HttpServletResponse response)22 throws ServletException, IOException {23 String username = request.getParameter("username");24 String passWord = request.getParameter("password");25 26 if ("admin".equals(username)&&"admin".equals(password)) {27 // 驗證通過28 HttpSession session = request.getSession();29 session.setAttribute("username", username);//把用戶名放入session中30 response.sendRedirect(request.getContextPath()+"/success.jsp");31 }else {32 // 驗證失敗33 response.sendRedirect(request.getContextPath()+"/failure.jsp");34 }35 }36 37 public void init() throws ServletException {38 39 }40 41 }LoginServlet.java如下圖所示:
現在我們要做這樣一件事:只有用戶登錄成功才可以訪問到success.jsp,反之跳轉到登錄界面。即:不允許未登錄用戶訪問success.jsp。
創建一個登錄校驗的過濾器LoginFilter并在web.xml中配置該過濾器的url為success.jsp
1 package servlet; 2 3 import java.io.IOException; 4 5 import javax.servlet.ServletException; 6 import javax.servlet.http.HttpServlet; 7 import javax.servlet.http.HttpServletRequest; 8 import javax.servlet.http.HttpServletResponse; 9 import javax.servlet.http.HttpSession;10 11 public class LoginServlet extends HttpServlet {12 13 public LoginServlet() {14 super();15 }16 17 public void destroy() {18 super.destroy(); // Just puts "destroy" string in log19 }20 21 public void doPost(HttpServletRequest request, HttpServletResponse response)22 throws ServletException, IOException {23 String username = request.getParameter("username");24 String password = request.getParameter("password");25 26 if ("admin".equals(username)&&"admin".equals(password)) {27 // 驗證通過28 HttpSession session = request.getSession();29 session.setAttribute("username", username);//把用戶名放入session中30 response.sendRedirect(request.getContextPath()+"/success.jsp");31 }else {32 // 驗證失敗33 response.sendRedirect(request.getContextPath()+"/failure.jsp");34 }35 }36 37 public void init() throws ServletException {38 39 }40 41 }LoginFilter.java1 <?xml version="1.0" encoding="UTF-8"?> 2 <web-app version="2.5" 3 xmlns="http://java.sun.com/xml/ns/javaee" 4 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 5 xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 6 http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> 7 <display-name></display-name> 8 <servlet> 9 <description>This is the description of my J2EE component</description>10 <display-name>This is the display name of my J2EE component</display-name>11 <servlet-name>LoginServlet</servlet-name>12 <servlet-class>servlet.LoginServlet</servlet-class>13 </servlet>14 15 <servlet-mapping>16 <servlet-name>LoginServlet</servlet-name>17 <url-pattern>/servlet/LoginServlet</url-pattern>18 </servlet-mapping> 19 <welcome-file-list>20 <welcome-file>index.jsp</welcome-file>21 </welcome-file-list>22 <filter>23 <filter-name>LoginFilter</filter-name>24 <filter-class>filter.LoginFilter</filter-class>25 </filter>26 <filter-mapping>27 <filter-name>LoginFilter</filter-name>28 <url-pattern>/success.jsp</url-pattern>29 </filter-mapping>30 </web-app>web.xml加入過濾器之后(只有成功登錄的用戶【session中保存了該用戶的用戶名】才可以訪問index.jsp):
在實際的開發中一個網站的頁面成百上千,這時我們可以使用通配符"/*"來匹配所有的url。但是這樣帶來一個問題:
當我們新建立一個session的時候,訪問任何頁面都會被重定向到login.jsp,login.jsp自己也重定向到login.jsp,這樣就形成了重定向循環
這時就需要在過濾器中判斷頁面是否是login.jsp,如果是login.jsp或者請求的是LoginServlet就直接放行。在LoginFilter的doFilter方法中添加這樣幾行代碼:
1 if (req.getRequestURI().indexOf("login.jsp")!=-1||req.getRequestURI().indexOf("LoginServlet")!=-1) {2 filterChain.doFilter(request, response); // 如果用戶請求的是login.jsp直接放行3 return; // 這一行代碼一定要加上啊!4 }運行結果:
上述程序看似已經沒有問題,但是還存在一個小bug,當我們在登陸頁輸入一個錯誤的用戶名和密碼頁面并不會重定向到failure.jsp而是重定向到了login.jsp。如下圖所示:
這是因為雖然我們在Servlet驗證失敗的時候將頁面重定向到了failure.jsp,failure.jsp又被過濾器重定向到了login.jsp【因為過濾規則為所有的頁面,并且session中沒有用戶名】
這時我們就會發現我們在doFilter中需要例外的頁面越來越多(登陸頁面、成功頁面、失敗頁面、錯誤頁面……)。為了減輕工作的復雜度,我們可以使用過濾器的init方法中的FilterConfig對象。
1. 在web.xml中配置不過濾頁面的初始化參數:
2. 在過濾方法中使用以上初始化參數。
1 public class LoginFilter implements Filter{ 2 3 private FilterConfig filterConfig;// 聲明一個FilterConfig對象 4 5 public void init(FilterConfig filterConfig) throws ServletException { 6 this.filterConfig = filterConfig; // 初始化方法的時候給filterConfig賦值 7 } 8 9 public void destroy() {10 11 }12 13 public void doFilter(ServletRequest request, ServletResponse response,14 FilterChain filterChain) throws IOException, ServletException {15 // 代碼省略16 }17 18 }3. 在doFilter方法中使用FilterConfig對象獲得初始化參數。
1 public void doFilter(ServletRequest request, ServletResponse response, 2 FilterChain filterChain) throws IOException, ServletException { 3 HttpServletRequest req = (HttpServletRequest) request; 4 HttpServletResponse res = (HttpSer
新聞熱點
疑難解答