1)JavaWEB 的一個重要組件,既可以對發送到 Servlet 的請求進行攔截,也可以對 Servlet 返回的響應進行攔截
2)Filter 是實現了 Filter 接口的 Java 類。與 Servlet 程序相似,它由 Servlet 容器進行調用和執行
3)Filter 程序需要在 web.xml 文件中進行註冊和設置它所能攔截的資源:Filter 程序可以攔截 Jsp, Servlet, 靜態圖片文件和靜態 html 文件
2.如何創建 Filter ,並運行 Filter
1)創建一個 Filter 類:實現 Filter 接口:public class HelloFilter implements Filter
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
public class HelloFilter implements Filter {
@Override
public void destroy() {
System.out.println("destroy...");
}
@Override
public void doFilter(ServletRequest arg0, ServletResponse arg1,
FilterChain arg2) throws IOException, ServletException {
System.out.println("doFilter...");
}
@Override
public void init(FilterConfig arg0) throws ServletException {
System.out.println("init...");
}
}
2)在 web.xml 文件中配置並映射該 Filter,其中 url-pattern 指定了該 Filter 可以攔截哪些資源,既可以通過那些 url 可以訪問到該 Filter
(1)<dispatcher>指定過濾器所攔截的資源被 Servlet 容器調用的方式,可以是REQUEST,INCLUDE,FORWARD和ERROR之一,默認REQUEST. 可以設置多個<dispatcher> 子元素用來指定 Filter 對資源的多種調用方式進行攔截
①REQUEST:當用戶直接訪問頁面時,Web容器將會調用過濾器。如果目標資源是通過RequestDispatcher的include()或forward()方法訪問時,那麼該過濾器就不會被調用。
②INCLUDE:如果目標資源是通過RequestDispatcher的include()方法訪問時,那麼該過濾器將被調用。除此之外,該過濾器不會被調用。
③FORWARD:如果目標資源是通過RequestDispatcher的forward()方法訪問時,那麼該過濾器將被調用,除此之外,該過濾器不會被調用。
④ERROR:如果目標資源是通過聲明式異常處理機制調用時,那麼該過濾器將被調用。除此之外,過濾器不會被調用。
<!-- 註冊 Filter -->
<filter>
<filter-name>helloFilter</filter-name>
<filter-class>com.javaweb.filter.HelloFilter</filter-class>
<!-- 配置初始化參數 -->
<init-param>
<param-name>user</param-name>
<param-value>root</param-value>
</init-param>
</filter>
<!-- 配置 Filter -->
<filter-mapping>
<filter-name>helloFilter</filter-name>
<url-pattern>/app1/hello.jsp</url-pattern>
</filter-mapping>
3)Filter 相關的 API
(1)Filter 接口的:
①public void init(FilterConfig arg0):類似與 Servlet 的 init 方法,在創建 Filter 對象(Filter 對象在 Servlet 容器加載當前 WEB 應用時即被創建)後,立即被調用,且只被調用一次。該方法用於對當前的 Filter 進行初始化操作
----a. FilterConfig:類似於 ServletConfig String getFilterName() ServletContext getServletContext() String getInitParameter(String name) Enumeration getInitParameterNames()
----b. 可以在 web.xml 文件中配置當前 Filter 初始化參數,配置方式也和 Servlet 方式一致
②public void doFilter(ServletRequest arg0, ServletResponse arg1,FilterChain arg2):真正 Filter 的邏輯代碼需要寫在該方法中,每次攔截都會調用該方法。
----a. FilterChain : Filter 鏈,多個 Filter 可以構成一個 Filter 鏈。
---------void doFilter(ServletRequest request,ServletResponse response):把請求傳給 Filter 鏈的下一個 Filter,若當前 Filter 是Filter 鏈的最後一個 Filter,將把請求給目標 Servlet(或JSP)
----b. 多個 Filter 攔截順序和<filter-mapping> 配置順序有關,靠前的先被調用。
③public void destroy()
(2)自定義的 HttpFilter
import java.io.IOException;
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;
import javax.servlet.http.HttpServletResponse;
public abstract class HttpFilter implements Filter {
private FilterConfig filterConfig;
//不建議子類直接覆蓋,若直接覆蓋可能導致 FilterConfig 對象初始化失敗
@Override
public void init(FilterConfig arg0) throws ServletException {
this.filterConfig = filterConfig;
init();
}
/**
* 供子類繼承的初始化方法,可以通過 getFilterConfig() 方法獲取 FilterConfige 對象
*/
protected void init() {}
public FilterConfig getFilterConfig() {
return filterConfig;
}
@Override
public void doFilter(ServletRequest req, ServletResponse rep,
FilterChain arg2) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) rep;
doFilter(request, response, arg2);
}
public abstract void doFilter(HttpServletRequest request,
HttpServletResponse response, FilterChain chain)
throws IOException, ServletException;
@Override
public void destroy() {
}
}
3.典型應用
1)使瀏覽器不緩存頁面的過濾器:
(1)有 3 個 HTTP 響應頭字段都可以禁止瀏覽器緩存當前頁面,它們在 Servlet 中的示例代碼如下:response.setDateHeader("Expires",-1); response.setHeader("Cache-Control","no-cache"); response.setHeader("Pragma","no-cache");
(2)並不是所有的瀏覽器都能完全支持上面的三個響應頭,因此最好是同時使用上面的三個響應頭
public class NoCache extends HttpFilter {
@Override
public void doFilter(HttpServletRequest request,
HttpServletResponse response, FilterChain chain)
throws IOException, ServletException {
response.setDateHeader("Expires",-1);
response.setHeader("Cache-Control","no-cache");
response.setHeader("Pragma","no-cache");
chain.doFilter(request, response);
}
}
2)字符編碼的過濾器:通過配置參數encoding指明使用何種字符編碼,以處理Html Form請求參數的中文問題
(1)
public class EncodingFilter extends HttpFilter {
private String encoding;
@Override
protected void init() {
encoding = getFilterConfig().getServletContext().getInitParameter("encoding");
}
public String getEncoding() {
return encoding;
}
@Override
public void doFilter(HttpServletRequest request,
HttpServletResponse response, FilterChain chain)
throws IOException, ServletException {
request.setCharacterEncoding(encoding);
chain.doFilter(request, response);
}
}