java web 過濾器filter


過濾器:

顧名思義,過濾器不能處理用戶請求,僅能過濾用戶請求。通過某些過濾規則,從過濾源中過濾出結果集合。

比如用戶訪問某些登錄可見的內容,會出現登錄的頁面,這就是過濾器要求http請求經過登錄。

過濾器在服務器端,截取用戶端的請求與響應信息,並對之進行過濾。

工作原理:

在web容器啟動時就加載了過濾器,它位於用戶和web資源之間,過濾請求與響應。

流程:實例化(發生於web容器加載) - > 初始化(調用init()方法) - > 過濾(調用doFilter()方法) - > 銷毀(調用destroy()方法,發生於web容器關閉)。

函數解析:

init(filterConfig arg0):arg0用來獲取web.xml中關於初始化的配置(init-param)。

doFilter(request, response, filterChain):過濾器的主函數,與該過濾器有關的url(定義於web.xml的filter-mapping中)都將進入此過濾器。在完成過濾后,可以調用filterChain的doFilter(request, response)方法,將請求傳往下一個filter或目標資源,故filterChain.doFilter方法稱為放行方法。也可以將請求轉發,重定向到其他資源(調用response.sendRedirect(request.getContextPath() + "url"))。(也可以導往403)

如果在重定向中出現循環(重定向到自己,或者兩個鏈接互相重定向),會導致死循環。在轉發中出現循環也會死循環。(詳見過濾器的分類)

destroy():在過濾器銷毀時被調用,釋放過濾器占用的資源。(一般不用)

過濾器配置:

在web.xml中,<filter>域用於配置過濾器類的類名(自己定義的過濾器將類名寫於此處),過濾器的初始化參數init-param也提供於此處,<filter-mapping>用於配置應用該過濾器的url(可以有多個)。

RD自己實現過濾器時,也可以調用Spring MVC自動加載filter,則filter-class寫org.springframework.web.filter.DelegatingFilterProxy,filter-name寫自己實現的過濾器類名(必然實現了Filter接口),並在類定義上方寫@Component("類名"),用於自動裝配。【常用】

過濾器使用方法:

過濾器可以用於過濾請求,也可以用於改變用戶請求的資源(對於符合過濾器請求的url)。

但是過濾器不能用於返回用戶請求,因為它不是一個標准的servlet。它可以將請求轉到目的資源,也可以將請求重定向到其他資源,但不可以返回數據給用戶。

過濾器鏈:

當web.xml中為同一個url定義了多個過濾器時,服務器會按照定義先后順序組成過濾器鏈,先后執行filter的doFilter方法(filterChain作為doFilter的第三個參數,會在doFilter的方法體中被調用:filterChain.doFilter(),將該request傳給下一個過濾器。

注意:定義在filterChain.doFilter()之后的方法,在servlet將response返回后,仍然會執行。且執行順序是:定義在最前面的過濾器,request將第一個經過該過濾器,但是其filterChain.doFilter()之后的代碼將在servlet返回response之后,作為response經過的最后的過濾器最后執行,之后將response返回給用戶。

過濾器的分類:

一共分為四種過濾器:REQUEST, FORWARD, INCLUDE, ERROR,在web.xml的<filter-mapping>域中<dispatcher>進行配置。默認是REQUEST,可復選。

REQUEST是默認的請求過濾器,即普通的請求都會進入。重定向的頁面也屬於普通的request。

事實上,重定向是服務器向客戶端發送一個302的頁面,客戶端獲取后,自動向重定向目的域名發送一個request,相當於兩次訪問。

FORWARD即轉發過濾器,當請求是通過轉發的方式獲得,進入該過濾器。轉發的定義如下:

重定向與轉發的區別:

重定向為response.sendRedirect(request.getContextPath() + "uri"),轉發為request.getRequestDispatcher("uri").forward(req,response)。(此為java,jsp也有自己的重定向、轉發方法。)前者主體是response,后者主體是request。

重定向告知客戶端瀏覽器重新請求頁面,其瀏覽器域名顯示將變化為新url,即重新發送REQUEST請求。

轉發是在服務器端,容器內部調用新界面,瀏覽器不知情,故瀏覽器域名不會變化,即在服務器內部生成FORWARD請求。

通常轉發比重定向性能更好一些。

INCLUDE為包含過濾器,當請求是通過包含的方式獲得,進入該過濾器。包含定義如下:

轉發與包含:

轉發為request.getRequestDispatcher("uri").forward(req,response),包含只需將forward換位include。轉發是將發往本頁面的請求轉到uri對應頁面,包含是在本頁面中同時包含了下一個uri的內容(意味着本頁面也會繼續執行)。

ERROR為錯誤過濾器,當請求是通過聲明式異常處理獲得,進入該過濾器。

常用的404導向頁面,可以通過配置web.xml實現。在web.xml中配置<error-page>,<error-code>填寫404,<location>填寫目標頁面(error.jsp)。

此時定義一個過濾器filter,配置dispatcher為ERROR,url為error.jsp,就可以在用戶輸錯網址時進入該過濾器。

如果不配置dispatcher,則只有用戶自己敲入error.jsp時才能捕捉,輸錯網址時不會被捕捉。(當然,如果想讓用戶端看到error.jsp,需要在末尾調用放行方法filterChain.doFilter())。

異步處理的新特性:

在servlet 3.0中,過濾器的dispatcher添加了ASYNC選項,作為異步處理特性。實際開發中多使用框架支持異步。

filter實踐中init-param的使用:

init-param在web.xml中配置,是一個<String,String>的鍵值對,可以在過濾器初始化時導入。

以登錄過濾功能為例,filter過濾所有頁面,進入session尋找“username”,沒有就重定向到login.jsp。從login.jsp讀取用戶名和密碼,正確就將信息存入session之后導向用戶本來訪問的頁面,錯誤就導向fail.jsp。那么login.jsp;fail.jsp都需要避免被filter循環攔截。

此時需要配置init-param,將noFilterURL(隨便起)作為key,不需攔截的域名統一存成一個String(可以用分號等間隔)作為value存入init-param。之后在filter中將init方法中的filterConfig參數保存下來(比如保存為private FilterConfig myConfig)。就可以調用myConfig.getInitParameter("noFilterURL")得到不需攔截的域名組成的String,將它split成單獨的字符串,當uri中可以匹配這些域名就放行加return,不再重定向。

此外,filter中可以添加request.setCharacterEncoding("UTF-8")用於將請求轉碼為Unicode,這樣就不需要再每個controller中去做處理,而是在filter進行統一處理。

也可以把"Encoding":"UTF-8"存入init-param中,用同樣的方法在filter中獲得這個配置項,用於設置轉碼。(這樣代碼的侵入度更低,低耦合)

 


免責聲明!

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



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