- Java EE 程序設計
- 郝玉龍編著
- 2403字
- 2019-07-01 10:16:07
3.10 Filter
Filter(過濾器)是Servlet 2.3規范以后增加的新特性。Filter攔截請求和響應,以便查看、提取或以某種方式操作正在客戶端和服務器之間交換的數據。Filter可以改變一個請求(Request)或者是修改響應(Response)。Filter與Servlet的關聯由Web應用的配置描述文件或注解來明確。用戶發送請求給Servlet時,在Servlet處理請求之前,與此Servlet關聯的Filter首先執行,然后才是Servlet的執行,Servlet執行完畢又會回到Filter。如果一個Servlet有多個Filter,則根據配置的先后次序依次執行。
Filter主要用在以下幾個方面:
(1)訪問特定資源(Web頁、JSP頁、Servlet)時的身份驗證。
(2)訪問資源的記錄跟蹤。
(3)訪問資源的轉換。
一個Filter必須實現javax.Servlet.Filter接口,即實現下面的三個方法:
(1)doFilter(ServletRequest, ServletResponse, FilterChain)。用來實現過濾行為的方法。引入的FilterChain對象提供了后續Filter所要調用的信息。
(2)init(FilterConfig)。由容器所調用的Filter初始化方法。容器確保在第一次調用doFilter方法前調用此方法,一般用來獲取在web.xml文件中指定的初始化參數。
(3)destroy()。容器在破壞Filter實例前,doFilter()中的所有活動都被該實例終止后,調用該方法。
下面演示如何利用Filter來記錄Web組件對請求的響應時間。首先生成一個Filter。在“項目”視圖中選中Web應用程序Chapter3,右擊,在彈出的快捷菜單中選擇“新建”→“文件/文件夾”命令,彈出“新建文件”對話框,如圖3-37所示。

圖3-37 創建Filter
在“類別”列表中選中Web,在“文件類型”列表中選中“過濾器”,單擊“下一步”按鈕,得到如圖3-38所示的“New過濾器”對話框。

圖3-38 Filter的名稱和位置
如圖3-38所示,在“類名”文本框中輸入Filter的名稱TimeTrackFilter,在“包”文本框中輸入包的名稱com.servlet,單擊“下一步”按鈕,得到如圖3-39所示的對話框。

圖3-39 配置Filter部署
在這里要配置過濾器的部署信息,即將過濾器與它要過濾的Web組件或URL模式關聯起來。
在“過濾器名稱”文本框中可以輸入過濾器的邏輯名稱,這里采用默認選項。單擊“編輯”按鈕打開“過濾器映射”對話框來設置過濾器映射信息,如圖3-40所示。

圖3-40 “過濾器映射”對話框
說明:過濾器有兩種映射模式。一種是對URL模式的映射,這也是默認的映射模式。在URL模式中可以使用通配符號,如“/*”。另外一種模式是對Servlet的映射,這時過濾器關聯的是Servlet的邏輯名稱。
選中單選按鈕URL,并在其右側的文本框中輸入“/Main”。單擊“確定”按鈕完成過濾器映射配置。此時Filter關聯的URL對應的組件為3.9節創建的Servlet Main。最后單擊圖3-39中的“完成”按鈕,Filter創建完畢。完整代碼如程序3-33所示。
程序3-33:TimeTrackFilter.java
… @WebFilter(filterName = "TimeTrackFilter", urlPatterns = {"/Main"}) public class TimeTrackFilter implements Filter { private FilterConfig filterConfig = null; public void init(FilterConfig filterConfig) throws ServletException { this.filterConfig = filterConfig; } public void destroy() { this.filterConfig = null; } public void doFilter( ServletRequest request, ServletResponse response, FilterChain chain ) throws IOException, ServletException { Date startTime, endTime; double totalTime; StringWriter sw = new StringWriter(); System.out.println("我在Filter中"); startTime = new Date(); chain.doFilter(request, response); endTime = new Date(); totalTime = endTime.getTime() - startTime.getTime(); totalTime = totalTime ; System.out.println("我在Filter中"); PrintWriter writer = new PrintWriter(sw); writer.println("==============="); writer.println("耗時:" + totalTime + " 毫秒" ); writer.println("==============="); filterConfig.getServletContext(). log(sw.getBuffer().toString()); } }
程序說明:跟Servlet一樣,在新版本的Java EE規范中,提供了注解WebFilter來部署Filter組件,其中屬性filterName為Filter的邏輯名稱,屬性urlPatterns為Filter的URL模式。
程序包含了所有Filter必須實現的3個接口方法:init、destroy和doFilter。當容器第一次加載該過濾器時,init方法將被調用。該類在這個方法中包含了一個指向FilterConfig對象的引用。對請求和響應的過濾功能主要由doFilter實現。Web容器在垃圾收集之前調用destroy方法,以便能夠執行任何必需的清理代碼。
TimeTrackFilter主要實現對過濾的Web組件處理耗時的跟蹤,在調用FilterChain對象的doFilter(request, response)方法之前創建一個Date對象startTime, FilterChain對象在doFilter(request, response)方法執行完畢后,控制權仍舊回到當前的Filter,此時,再創建一個Date對象endTime來獲取當前時刻,二者相減,就得到被過濾Web組件的執行時間。
為了使執行效果更明顯,可以修改Servlet Main,使Servlet的線程暫時中止2秒。修改后的代碼如程序3-34所示。
程序3-34:Main.java
package com.servlet; … public class Main extends HttpServlet { protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{ System.out.println("我在Servlet Main中"); try{ Thread.sleep(2000); }catch (InterruptedException ie){ System.out.println(ie.toString()); } String userID=request.getParameter("userID"); … }
程序說明:斜體部分為新增的代碼,即調用Thread對象的sleep方法使線程暫停2秒。
重新發布Web應用,打開IE瀏覽器,在地址欄中輸入http://localhost:8080/Chapter3/dl.html,得到如圖3-34所示的運行結果頁面。在“用戶名”文本框輸入guest,在“密碼”文本框輸入guest,單擊“提交”按鈕,此時瀏覽器向URL模式“/Main”發出請求,由于URL模式“/Main”被關聯到Filter TimeTrackFilter,則首先執行TimeTrackFilter的doFilter方法,然后執行Servlet Main,最后又回到Filter的doFilter方法。因此在Netbeans底部的“輸出”窗口的GlassFish Server 3.1.1中可以看到如圖3-41的輸出信息。

圖3-41 Filter運行過程中的輸出信息
從上面的演示過程可以看出,開發人員不應當把Filter看作是請求到達Servlet之前的一道防火墻,而應當把它看作是包裹在Servlet組件外面的一層防護網。在請求到達Servlet前后都會經過Filter的處理。
Filter不僅可以對URL模式進行過濾,還可以對Servlet組件的邏輯名稱進行過濾。下面為TimeTrackFilter添加對Servlet組件PDFServlet的過濾。打開web.xml,在編輯器中選中“過濾器”視圖,得到如圖3-42所示的運行界面。

圖3-42 修改Filter配置信息
單擊“過濾器映射”下的“添加”按鈕,彈出“編輯過濾器映射”對話框,如圖3-43所示。

圖3-43 修改Filter配置信息
選中“Servlet名稱”單選按鈕,在其右邊的下拉列表中選中要過濾的Servlet的名稱PDFServlet,單擊“確定”按鈕,完成TimeTrackFilter對Servlet組件PDFServlet的過濾設置。
重新發布Web應用,打開IE瀏覽器,在地址欄中輸入http://localhost:8080/Chapter3/pdfshow,在Netbeans底部的“輸出”窗口的GlassFish Server 3.1.1視圖中可以看到執行Servlet組件PDFServlet的耗時信息。
在Servlet 2.4以上的Web容器中,過濾器可以根據請求分發器(request dispatcher)所使用的方法有條件地對Web請求進行過濾。在圖3-43中,在“分發程序類型”組中可以看到四個檢查框,分別代表以下分發類型:
·REQUEST——只有當request直接來自客戶,過濾器才生效。
·FORWARD——只有當request被一個請求分發器使用forward方法轉到另一個Web組件時,過濾器才生效。
·INCLUDE——只有當request被一個請求分發器使用include方法轉到一個Web構件時,過濾器才生效。
·ERROR——只有當request被一個請求分發器使用“錯誤信息頁”機制方法轉到一個Web組件時,過濾器才生效。
以上四個條件可以組合使用。
在圖3-39中,選中Filter的映射項PDFServlet,單擊“編輯”按鈕來修改映射信息。在彈出的“編輯過濾器映射”對話框中,選中FORWARD復選框,如圖3-44所示。單擊“確定”按鈕,完成對過濾器映射信息的修改。

圖3-44 修改Filter映射信息
重新發布Web應用,打開IE瀏覽器,在地址欄中輸入http://localhost:8080/Chapter3/pdfshow,在Netbeans底部的“輸出”窗口的GlassFish Server 3.1.1視圖中將看不到Filter輸出的執行Servlet組件PDFServlet的耗時信息。因為按照修改后的Filter映射設置,只有調用請求分發器的forward方法對Servlet組件PDFServlet發送請求才被過濾器過濾。
- Java程序設計與開發
- 深入理解Android(卷I)
- Learning Cython Programming(Second Edition)
- Linux C/C++服務器開發實踐
- 編程珠璣(續)
- 信息安全技術
- JavaScript從入門到精通(第3版)
- 零基礎學Java程序設計
- Express Web Application Development
- Learning Apache Cassandra
- Procedural Content Generation for C++ Game Development
- LabVIEW虛擬儀器入門與測控應用100例
- 搞定J2EE:Struts+Spring+Hibernate整合詳解與典型案例
- C++程序設計教程(第2版)
- OpenCV 3.0 Computer Vision with Java