一、簡介 作用:對Servlet容器調用Servlet的過程進行攔截,從而在Servlet進行響應處理的前後實現一些特殊的功能。 過濾器 API:Filter,FilterChain,FilterConfig。 Filter 程式:實現了 Filter 介面的 Java 類,由Servlet容器進行 ...
一、簡介
作用:對Servlet容器調用Servlet的過程進行攔截,從而在Servlet進行響應處理的前後實現一些特殊的功能。
過濾器 API:Filter,FilterChain,FilterConfig。
Filter 程式:實現了 Filter 介面的 Java 類,由Servlet容器進行調用和執行,需要在 web.xml 中進行註冊和設置它所能攔截的資源。
原理:Filter可以對Servlet容器發送給Servlet程式的請求和Servlet程式回送給Servlet容器的響應進行攔截。可以決定是否將請求繼續傳遞給Servlet程式,以及對請求和響應信息是否進行修改。
二、使用方法
1)void init(FilterConfig filterConfig)
作用:類似於 Servlet 的 init 方法。在創建 Filter 對象(Filter 對象在 Servlet 容器載入當前 WEB 應用時即被創建)後,立即被調用, 且只被調用一次。該方法用於對當前的 Filter 進行初始化操作。Filter 實例是單例的。
- FilterConfig 類似於 ServletConfig
- 可以在 web.xml 文件中配置當前 Filter 的初始化參數. 配置方式也和 Servlet 類似。
2)void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
作用:真正 Filter 的邏輯代碼需要編寫在該方法中。每次攔截都會調用該方法。
參數:FilterChain:Filter 鏈。多個 Filter 可以構成一個 Filter 鏈。
- chain.doFilter(ServletRequest request, ServletResponse response):把請求傳給 Filter 鏈的下一個 Filter,若當前 Filter 是 Filter 鏈的最後一個 Filter,將把請求給到目標 Serlvet(或 JSP)。
- 多個 Filter 攔截的順序和 <filter-mapping> 配置的順序有關,靠前的先被調用。
3)public void destroy()
釋放當前 Filter 所占用的資源的方法。在 Filter 被銷毀之前被調用,且只被調用一次。
public class HelloFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest request, ServletResponse response,FilterChain chain)
throws IOException, ServletException {//放行 chain.doFilter(request, response); } @Override public void destroy() { } }
web.xml
url-pattern:指定該 Filter 可以攔截哪些資源,即可以通過哪些 url 訪問到該 Filter。
<dispatcher>:指定過濾器所攔截的資源被 Servlet 容器調用的方式,可以是REQUEST,INCLUDE,FORWARD和ERROR之一,預設REQUEST。可以設置多個<dispatcher> 子元素用來指定 Filter 對資源的多種調用方式進行攔截
- REQUEST:當用戶直接訪問頁面時,Web 容器將會調用過濾器。如果目標資源是通過 RequestDispatcher 的 include() 或 forward() 方法訪問時,那麼該過濾器就不會被調用。通過 GET 或 POST 請求直接訪問。
- FORWARD:如果目標資源是通過 RequestDispatcher 的 forward() 方法訪問時,那麼該過濾器將被調用,除此之外,該過濾器不會被調用。或 <jsp:forward page="/..." /> 或 通過 page 指令的 errorPage 轉發頁面. <%@ page errorPage="test.jsp" %>
- INCLUDE:如果目標資源是通過 RequestDispatcher 的 include() 方法訪問時,那麼該過濾器將被調用。除此之外,該過濾器不會被調用。或 <jsp:include file="/..." />
- ERROR:如果目標資源是通過聲明式異常處理機制調用時,那麼該過濾器將被調用。除此之外,過濾器不會被調用。在 web.xml 文件中通過 error-page 節點進行聲明:
<error-page> <exception-type>java.lang.ArithmeticException</exception-type> <location>/test.jsp</location> </error-page>
<!-- 註冊 Filter --> <filter> <filter-name>helloFilter</filter-name> <filter-class>com.atguigu.javaweb.HelloFilter</filter-class> </filter> <!-- 映射 Filter --> <filter-mapping> <filter-name>helloFilter</filter-name> <url-pattern>/test.jsp</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
<dispatcher>INCLUDE</dispatcher>
<dispatcher>ERROR</dispatcher>
</filter-mapping>
三、應用
1. 使瀏覽器不緩存頁面的過濾器
有3個HTTP響應頭欄位都可以禁止瀏覽器緩存當前頁面
- HttpServletResponse.setDataHeader("Expires", -1);
- HttpServletResponse.setHeader("Cache-Control", "no-cache");
- HttpServletResponse.setHeader("Pragma", "no-cache");
//HttpFilter的實現與HttpServlet相似
public class NoCacheFilter extends HttpFilter { @Override public void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws IOException, ServletException { response.setDateHeader("Expires",-1); response.setHeader("Cache-Control","no-cache"); response.setHeader("Pragma","no-cache"); filterChain.doFilter(request, response); } }
2. 字元編碼的過濾器
目標:讓所有的頁面都不會出現字元編碼問題,為此需要添加一個過濾器
EncodingFilter.java
public class EncodingFilter extends HttpFilter{ private String encoding; @Override protected void init() { encoding = getFilterConfig().getServletContext().getInitParameter("encoding"); } @Override public void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws IOException, ServletException { System.out.println(encoding); request.setCharacterEncoding(encoding); filterChain.doFilter(request, response); } }
web.xml
<context-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </context-param> <filter> <filter-name>encodingFilter</filter-name> <filter-class>com.atguigu.javaweb.encoding.EncodingFilter</filter-class> </filter> <filter-mapping> <filter-name>encodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>