標籤:
本人部落格:http://wxmimperio.coding.io/
本人郵箱:[email protected]
一、過濾器的介紹:
- 在Servlet規範2.3中定義了過濾器,它是一個伺服器端的組件,可以截取使用者端的請求與響應資訊,並且對這些資訊進行過濾。
- Servlet過濾器本身並不產生請求和響應對象,只是提供過濾功能。
- Servlet過濾器能夠在Servlet被調用之前檢查Request對象,並修改Request Header和Request內容。
- Servlet過濾器可以過濾的Web組件包括Servlet,JSP和HTML等檔案。
本文源碼——GitHub:
https://github.com/imperio-wxm/wordpressCode/tree/master/Filter
二、過濾器在實際開發中的應用情境1.對使用者請求進行統一認證2.編碼轉換3.對使用者發送的資料進行過濾替換4.轉換映像格式5.對相應的內容進行壓縮三、過濾器的工作原理
【沒有過濾器】:
使用者直接存取WEB資源。
【有過濾器】:
WEB容器啟動時進行過濾器的載入,使用者發出請求到過濾器,過濾器判斷請求是否符合規則,符合規則的請求通過過濾器發送給WEB資源,WEB資源響應的資訊返回給過濾器,過濾器再將WEB資源的響應返回給使用者。
四、過濾器的生命週期(類似Servlet的生命週期)
1.執行個體化——通過web.xml進行配置載入,在容器啟動時只會執行個體化一次
2.初始化——調用init()方法,載入資訊只會執行一次
3.過濾——使用doFilter()方法進行多次過濾
4.銷毀——WEB容器關閉時調用destroy()方法進行銷毀
所有的Servlet過濾器都必須實現javax.servlet.Filter介面,並實現該介面中的三個方法。
【init()方法】
- 這是過濾器的初始化方法,web容器建立過濾器執行個體後將調用這個方法。這個方法中可以web.xml檔案中過濾器的參數。
【doFilter()方法】
- 這個方法完成實際的過濾操作。這個地方是過濾器的核心方法,當使用者請求訪問與過濾器關聯的URL時,web容器將先調用過濾器的doFilter方法。
- FilterChain方法參數可以調用chain.doFilter方法,將請求傳給下一個過濾器(或目標資源),或利用轉寄、重新導向請求轉寄到其他資源。
【destroy()方法】
- web容器在銷毀過濾器執行個體前調用該方法,在這個方法中可以釋放過濾器佔用的資源。
【生命週期代碼示範】
package com.filter;import javax.servlet.*;import java.io.IOException;/** * Created by wxm-Imperio */public class FirstFilter implements Filter { @Override public void destroy() { System.out.println("destroy,firstFilter"); } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
throws IOException, ServletException { System.out.println("start,doFilter,firstFilter"); filterChain.doFilter(servletRequest, servletResponse); System.out.println("End,doFilter,firstFilter"); } @Override public void init(FilterConfig filterConfig) throws ServletException { System.out.println("init。firstFilter"); }}
【web.xml配置】
<filter> <filter-name>Filter的名字</filter-name> <filter-class>Filter類的名字</filter-class> <init-param> <description>描述資訊可以省略或者放在此處</description> <param-name>參數名稱</param-name> <param-value>參數的值</param-value> </init-param></filter><filter-mapping> <filter-name>Filter的名字</filter-name> <url-pattern>URL</url-pattern> <dispatcher></dispatcher>//過濾器類型</filter-mapping>
注意:一般Filter配置在所有的Servlet之前。
五、支援多個過濾器
- 每個過濾器有不同的URL地址
- 當不同的過濾器URL地址相同時,會產生過濾器鏈:
- 使用者請求——依次每個過濾器——web資源(順序是:伺服器按照web.xml中過濾器定義的先後順序組成一條鏈)
【使用者請求】——>【過濾器1Chain.doFilter前代碼——>過濾器1Chain.doFilter——>過濾器2Chain.doFilter前代碼——>過濾器1Chain.doFilter.......】——>【Servlet的Service方法處理請求】——>...........【過濾器2Chain.doFilter後代碼——>過濾器1Chain.doFilter後代碼】——>【返回使用者請求】
【過濾器鏈的web.xml配置】
<!--過濾器1的配置資訊--!><filter> <filter-name>Filter1的名字</filter-name> <filter-class>Filter1類的名字</filter-class> <init-param> <description>描述資訊可以省略或者放在此處</description> <param-name>參數名稱</param-name> <param-value>參數的值</param-value> </init-param></filter><filter-mapping> <filter-name>Filter1的名字</filter-name> <url-pattern>URL</url-pattern> <dispatcher></dispatcher>//過濾器類型</filter-mapping><!--過濾器2的配置資訊--!><filter> <filter-name>Filter2的名字</filter-name> <filter-class>Filter2類的名字</filter-class> <init-param> <description>描述資訊可以省略或者放在此處</description> <param-name>參數名稱</param-name> <param-value>參數的值</param-value> </init-param></filter><filter-mapping> <filter-name>Filter2的名字</filter-name> <url-pattern>URL</url-pattern> <dispatcher></dispatcher>//過濾器類型</filter-mapping>
注意:過濾器的執行順序就是在web.xml裡配置的順序。
六、過濾器的分類
Servlet2.5:
1.REQUEST(預設)使用者直接存取頁面時,web容器將會調用過濾器。2.FORWORD 目標源是通過RequestDispatcher的forword方法訪問時,該過濾器被調用。3.INCLUDE 目標資源時通過RequestDispatcher的include方法調用時,過濾器被調用。4.ERROR 目標資源是通過聲明式異常處理機制調用時,過濾器將被調用。 【文法】
@WebFilter(servletNames = {"SimpleServlet"} filterName = "SimpleFilter")public class LessThanSixFilter implements Filter {//類中內容}
【ERROR的配置資訊】
<error-page> <error-code>404</error-code> <location>/error.jsp</location></error-page><filter> <filter-name>errorFilter</filter-name> <filter-class>com.filter.ErrorFilter</filter-class></filter><filter-mapping> <filter-name>errorFilter</filter-name> <url-pattern>/error.jsp</url-pattern></filter-mapping>
【ErrorFilter過濾器代碼】
public class ErrorFilter implements Filter { @Override public void destroy() { } @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
throws IOException, ServletException { System.out.println("檢測到有錯誤資訊"); }}
Servlet3.0:
(新增)ASYNC 支援非同步處理
- @WebFilter(引言)用於將一個聲明為過濾器,該註解將會在部署時被容器處理,容器將根據具體的屬性配置相應的類部署為過濾器
【非同步作業處理代碼:過濾器不等待線程,直接執行後面內容,實現非同步處理】
AsynServlet
//設定Servlet支援非同步@WebServlet(name = "AsynServlet", asyncSupported = true)public class AsynServlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException { System.out.println("Servlet執行開始時間" + new Date()); //實現非同步作業 AsyncContext context = request.startAsync(); //開啟非同步線程 new Thread(new Executor(context)).start(); System.out.println("Servlet執行結束時間" + new Date()); } protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException { doPost(request, response); } //內部類類比線程 public class Executor implements Runnable { private AsyncContext context; //實現構造方法 public Executor(AsyncContext context) { this.context = context; } @Override public void run() { //執行相關的複雜業務 try { Thread.sleep(1000 * 10); //context.getRequest(); //context.getResponse(); System.out.println("業務執行完成時間" + new Date()); } catch (InterruptedException e) { e.printStackTrace(); } } }}
AsvnFilter過濾器
//註解@WebFilter(filterName =
"AsynFilter", value = {"/AsynServlet"}, asyncSupported = true, dispatcherTypes = {DispatcherType.REQUEST,DispatcherType.ASYNC})public class AsynFilter implements Filter { @Override public void destroy() { } @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
throws IOException, ServletException { System.out.println("Start..........AsynFilter"); filterChain.doFilter(servletRequest, servletResponse); System.out.println("End..........AsynFilter"); }}
web.xml配置
<servlet> <servlet-name>AsynServlet</servlet-name> <servlet-class>com.servlet.AsynServlet</servlet-class></servlet><servlet-mapping> <servlet-name>AsynServlet</servlet-name> <url-pattern>/AsynServlet</url-pattern></servlet-mapping>
七、FilterConfig的使用
Filter的init方法中提供了一個FilterConfig對象,提供相關的操作:
如擷取Filter中配置的初始化參數web.xml配置:
<filter> <filter-name>LoginFilter</filter-name> <filter-class>com.itzhai.login.LoginFilter</filter-class> <init-param> <param-name>username</param-name> <param-value>arthinking</param-value> </init-param></filter>
在init()方法中擷取:
@Overridepublic void init(FilterConfig filterConfig) throws ServletException { //擷取Filter初始化參數 String username = filterConfig.getInitParameter("username");}
在Filter中訪問application:
ServletContext context = filterConfig.getServletContext();
也可以在doFilter方法中根據轉換好的request擷取:
HttpServletRequest req = (HttpServletRequest)request;ServletContext context = req.getSession().getServletContext();
八、項目執行個體
慕課網中使用者登入的加強版Demo,利用過濾器對用於請求和伺服器回應進行過濾。
GitHub源碼:https://github.com/imperio-wxm/projectDemo
參考:JSP應用開發詳解(第三版)、慕課網
Java Web進階——Filter過濾器