## 一、Filter 的基本工作原理
* 1、Filter 程序是一個實現了特殊接口的 Java 類,與 Servlet 類似,也是由 Servlet 容器進行調用和執行的。
* 2、當在 web.xml 注冊了一個 Filter 來對某個 Servlet 程序進行攔截處理時,它可以決定是否將請求繼續傳遞給 Servlet 程序,以及對請求和響應消息是否進行修改。
* 3、當 Servlet 容器開始調用某個 Servlet 程序時,如果發現已經注冊了一個 Filter 程序來對該 Servlet 進行攔截,那么容器不再直接調用 Servlet 的 service 方法,而是調用 Filter 的 doFilter 方法,再由 doFilter 方法決定是否去激活 service 方法。
* 4、但在 Filter.doFilter 方法中不能直接調用 Servlet 的 service 方法,而是調用 FilterChain.doFilter 方法來激活目標 Servlet 的 service 方法,FilterChain 對象時通過 Filter.doFilter 方法的參數傳遞進來的。
* 5、只要在 Filter.doFilter 方法中調用 FilterChain.doFilter 方法的語句前后增加某些程序代碼,這樣就可以在 Servlet 進行響應前后實現某些特殊功能。
* 6、如果在 Filter.doFilter 方法中沒有調用 FilterChain.doFilter 方法,則目標 Servlet 的 service 方法不會被執行,這樣通過 Filter 就可以阻止某些非法的訪問請求。
* * *
## 二、Filter 鏈
* 1、在一個 Web 應用程序中可以注冊多個 Filter 程序,每個 Filter 程序都可以對一個或一組 Servlet 程序進行攔截。如果有多個 Filter 程序都可以對某個 Servlet 程序的訪問過程進行攔截,當針對該 Servlet 的訪問請求到達時,Web 容器將把這多個 Filter 程序組合成一個 Filter 鏈(也叫過濾器鏈)。
* 2、Filter 鏈中的各個 Filter 的攔截順序與它們在 web.xml 文件中的映射順序一致,上一個 Filter.doFilter 方法中調用 FilterChain.doFilter 方法將激活下一個 Filter的doFilter 方法,最后一個 Filter.doFilter 方法中調用的 FilterChain.doFilter 方法將激活目標 Servlet的service 方法。
* 3、只要 Filter 鏈中任意一個 Filter 沒有調用 FilterChain.doFilter 方法,則目標 Servlet 的 service 方法都不會被執行。
* * *
## 三、Filter 接口
一個 Filter 程序就是一個 Java 類,這個類必須實現 Filter 接口。javax.servlet.Filter 接口中定義了三個方法:init、doFilter、destory。
**1、init 方法**
* (1)、在 Web 應用程序啟動時,Web 服務器(Web 容器)將根據其 web.xml 文件的配置信息來創建每個注冊的 Filter 的實例對象,并將其保存在內存中。
* (2)、Web 容器創建 Filter 的實例對象后,將立即調用該 Filter 對象的 init 方法。init 方法在 Filter 生命周期中僅被執行一次,Web 容器在調用 init 方法時,會傳遞一個包含 Filter 的配置和運行環境信息的 FilterConfig 對象。
~~~
public voic init(FilterConfig filterConfig) throws ServletException
~~~
* (3)開發人員可以在 init 方法中完成與構造方法類似的初始化功能,要注意的是:如果初始化代碼要使用到 FilterConfig 對象,這些代碼只能在 init 方法中編寫,而不能在構造方法中編寫(尚未調用 init 方法,即并沒有創建 FilterConfig 對象,要使用它則必然出錯)。
### 2、doFilter 方法
當一個 Filter 對象能夠攔截訪問請求時,Servlet 容器將調用 Filter 對象的 doFilter 方法。
~~~
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws java.io.IOException.ServletException
~~~
其中,參數 request 和 response 為 Web 容器或 Filter 鏈中上一個 Filter 傳遞過來的請求和響應對象;參數 chain 為代表當前 Filter 鏈的對象。
### 3、destroy 方法
該方法在 Web 容器卸載 Filter 對象之前被調用,也僅執行一次。可以完成與 init 方法相反的功能,釋放被該 Filter 對象打開的資源,例如:關閉數據庫連接和 IO 流。
* * *
## 四、FilterChain 接口
該接口用于定義一個 Filter 鏈的對象應該對外提供的方法,這個接口只定義了一個 doFilter 方法。
~~~
public void doFilter(ServletRequest request, ServletResponse response) throws java.io.IOException.ServletException
~~~
FilterChain 接口的 doFilter 方法用于通知 Web 容器把請求交給 Filter 鏈中的下一個 Filter 去處理,如果當前調用此方法的 Filter 對象是Filter 鏈中的最后一個 Filter,那么將把請求交給目標 Servlet 程序去處理。
* * *
## 五、FilterConfig 接口
* 1、與普通的 Servlet 程序一樣,Filter 程序也很可能需要訪問 Servlet 容器。Servlet 規范將代表 ServletContext 對象和 Filter 的配置參數信息都封裝到一個稱為 FilterConfig 的對象中。
* 2、FilterConfig 接口則用于定義 FilterConfig 對象應該對外提供的方法,以便在 Filter 程序中可以調用這些方法來獲取 ServletContext 對象,以及獲取在 web.xml 文件中為 Filter 設置的友好名稱和初始化參數。
* 3、FilterConfig接口定義的各個方法:
* getFilterName 方法,返回 元素的設置值。
* getServletContext 方法,返回 FilterConfig 對象中所包裝的 ServletContext 對象的引用。
* getInitParameter 方法,用于返回在 web.xml 文件中為 Filter 所設置的某個名稱的初始化的參數值。
* getInitParameterNames 方法,返回一個 Enumeration 集合對象。
* * *
## 六、Filter 的注冊與映射
### 1、注冊 Filter
一個 元素用于注冊一個 Filter。其中, 元素是必需的, 元素也是必需的, 元素是可選的,可以有多個 元素。
~~~
<filter>
<filter-name>FirstFilter</filter-name>
<filter-class>FirstFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>GB2312</param-value>
</init-param>
</filter>
~~~
### 2、映射 Filter
元素用于設置一個 Filter 所負責攔截的資源。一個 Filter 攔截的資源可以通過兩種方式來指定:資源的訪問請求路徑和 Servlet 名稱。
**第一種:指定資源的訪問路徑**
~~~
<filter-mapping>
<filter-name>FirstFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
~~~
元素中的訪問路徑的設置方式遵循 Servlet 的 URL 映射規范。
* /\*:表示攔截所有的訪問請求。
* /filter/\*:表示攔截 filter 目錄下的所有訪問請求,如:http://localhost:8888/testFilter\_001/filter/xxxxxx 。
* /test.html:表示攔截根目錄下以 test.html 為資源名的訪問請求,訪問鏈接只會是:http://localhost:8888/test.html。
**第二種:指定 Servlet 的名稱**
~~~
<filter-mapping>
<filter-name>FirstFilter</filter-name>
<servlet-name>default></servlet-name>
<dispatcher>INCLUDE</dispatcher>
<dispatcher>REQUEST</dispatcher>
</filter-mapping>
~~~
(1)、 元素與 元素是二選一的關系,其值是某個 Servlet 在 web.xml 文件中的注冊名稱。
(2)、 元素的設置值有 4 種:REQUEST、INCLUDE、FORWARD、ERROR,分別對應 Servlet 容器調用資源的 4 種方式:
* 通過正常的訪問請求調用;
* 通過 RequestDispatcher.include 方法調用;
* 通過 RequestDispatcher.forward 方法調用;
* 作為錯誤響應資源調用。
如果沒有設置 子元素,則等效于 REQUEST 的情況。也可以設置多個 子元素,用于指定 Filter 對資源的多種調用方式都進行攔截。
* * *
## 七、Filter 程序示例
## FitstFilter.java
```
package cn.baishenghua.web.filter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Enumeration;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
public class FirstFilter implements Filter {
private FilterConfig filterConfig = null;
String paramValue = null;
@Override
public void init(FilterConfig filterConfig) throws ServletException {
this.filterConfig = filterConfig;
paramValue = filterConfig.getInitParameter("encoding");
}
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
System.out.println("begin headers-------------------");
Enumeration<?> headerNames = ((HttpServletRequest)request).getHeaderNames();
while(headerNames.hasMoreElements()) {
String headerName = (String)headerNames.nextElement();
System.out.println(headerName + ": " + ((HttpServletRequest)request).getHeader(headerName));
}
System.out.println("end headers-------------------");
//在調用目標前寫入響應內容
response.setContentType("text/html; charset=gb2312");
PrintWriter out = response.getWriter();
out.println("IP地址為:" + request.getRemoteHost() + "<br>");
chain.doFilter(request, response);
//在目標返回后寫入響應內容
out.println("<br>名稱為encoding的初始化參數的值為:" + paramValue);
out.println("<br>當前Web程序的真實路徑為:" + filterConfig.getServletContext().getRealPath("/"));
//out.println("<br>修改了test.html文件!");
}
@Override
public void destroy() {
this.filterConfig = null;
}
}
```
## web.xml
```
<filter>
<filter-name>FirstFilter</filter-name>
<filter-class>FirstFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>GB2312</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>FirstFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
```
## test.html(位于WebContent路徑的filter目錄中)
```
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body> 這就是test.html頁面的原始內容! </body>
</html>
```
訪問:**http://localhost:8888/testFilter\_001/filter/test.html**
- Java Web項目開發學習手冊
- 一、B/S開發環境搭建
- 1.1 tomcat服務器目錄結構及作用
- 1.2 在IDE開發工具上配置tomcat服務器
- 1.3 簡單web項目在tomcat服務器上運行的方法
- 1.4 開發工具設置
- 1.5 總結
- 二、Servlet技術應用
- 2.1 HttpServlet中的主要方法及應用
- 2.1.1 基于Eclipse完成一個JavaWeb項目
- 2.2 HttpRequest,HttpResponse的應用
- 2.2.1客戶端請求
- 2.2.2服務器響應
- 2.2.3Servlet HTTP 狀態碼
- 2.2.4圖片驗證碼類
- 2.2.5注冊模擬實現(帶驗證碼)
- 2.3 ServletConfig對象和ServletContext對象的概念
- 2.4 總結
- 三、JSP技術應用
- 3.1 JSP基本語法
- 3.2 JSP標簽和指令
- 3.3 JSP中的隱式對象
- 3.4 常用應用操作
- 3.4.1 JSP客戶端請求
- 3.4.2 JSP服務器響應
- 3.4.3 HTTP狀態碼
- 3.4.4 表單處理
- 3.4.5 過濾器
- 3.4.6 Cookie處理
- 3.4.7 Session處理
- 3.4.8 文件上傳
- 3.4.9 日期處理
- 3.4.10 頁面重定向
- 3.4.11 點擊量統計
- 3.4.12 自動刷新
- 3.4.13 發送郵件
- 3.5 JSP高級應用
- 3.5.1 JSP標準標簽庫(JSTL)
- 3.5.2 JSP連接數據庫
- 3.5.3 JSP XML數據處理
- 3.5.4 JSP JavaBean
- 3.5.5 自定義標簽
- 3.5.6 表達式語言
- 3.5.7 異常處理
- 3.5.8 調試
- 3.5.9 JSP國際化
- 3.6 實踐代碼
- 3.6.1 實踐代碼
- 3.6.2 項目實戰
- 3.7 總結
- 四、MVC思想的理解和搭建MVC
- 4.1 MVC設計模式的思想
- 4.2 MVC設計模式的實現步驟
- 4.3 項目實踐
- 4.4 總結
- 五、EL表達式和JSTL技術
- 5.1 EL表達式及其應用
- 5.2 常用的JSTL標簽的應用
- 5.3 項目實踐
- 5.4 總結
- 六、Cookie和Session
- 6.1 cookie對象的概念和應用
- 6.2 session對象的概念和應用
- 6.3 項目實踐
- 6.4 總結
- 七、過濾器技術應用
- 7.1 Filter的概念及應用
- 7.2 Filter、FilterChain、FilterConfig 介紹
- 7.3 用戶登錄過濾案例
- 7.4 項目實戰
- 7.5總結
- 八、異步請求技術
- 8.1 JSON數據格式
- 8.2 使用AJAX實現異步請求
- 8.3 用戶名校驗案例
- 8.4小結
- 綜合項目技術實訓
- 1.BS項目開發項目實戰
- 2.項目需求分析和系統設計
- 2.1需求分析
- 2.2類型模型設計
- 2.3原型設計
- 3.項目數據庫分析和系統設計
- 4.BS項目編程實現
- 4.1搭建框架和命名規約
- 4.2實現步驟
- 4.2.1創建實體類
- 4.2.2創建過濾器類
- 4.2.3創建工具類
- 4.2.4創建DAO接口及其實現類
- 4.2.5創建Service接口及其實現類
- 4.2.6創建測試類
- 4.2.7創建控制器類
- 5.企業開發流程規范
- 6.總結
- 九、練習題及答案
- 企業開發常用技術
- 1.Maven技術
- Java命名規范解讀
- 參考資料
- 開發中常用的應用服務器和Web服務器