Filter快速入門
開始學習Filter這個知識點,單詞是過濾器和攔截器的作用。Filter是Javaweb中的過濾器,可以攔截所有訪問web資源的請求或響應操作。Filter這個知識點很重要,在javaweb開發中,這個是我們需要重點掌握的一個知識點。
1.使用場景
使用Filter主要場景是攔截判斷是否登錄,權限管理,例如不同角色權限是不同,請求在這個角色之外的操作會被攔截。還有一個使用場景就是全局給項目中全部servlet都設置UTF-8編碼,防止中文亂碼的情況。
這裡,我們來看線上產品,某一家公司的登錄攔截,使用了Filter,我們看看效果。
瀏覽器打開
點擊上圖中,紅圈的結構式檢索,看看登錄攔截效果。
立馬就讓你去登錄,這個就是一個典型的使用Filter的場景。
這裡簡單來分析一下這個攔截過程:
1) 用戶沒有登錄,點擊結構式檢索這個請求
2) 這個請求發送到伺服器上對應的Servlet處理之前被Filter給攔截了
3) 在Filter中代碼先從session中取出用戶數據,看看用戶是否存在
4) 如果用戶是null,說明沒有登錄,需要攔截
5) 如果用戶是資料庫中存在用戶,放開攔截,讓請求繼續下去
下面,我們來一個Filter快速入門的練習,體會一下這個攔截和放行的過程。
2.Filter快速入門步驟
1)創建一個類實現Filter接口
2)重寫接口中方法,doFilter方法是真正過濾的。
3)在web.xml文件中配置
在Filter的doFilter方法內如果沒有執行chain.doFilter(request,response),那麼資源是不會被訪問到的。
3.Filter入門練習
創建一個web項目
新建一個Servlet類,待會要用,模擬我們的上面這個結構式檢索對應的Servlet。
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class ServletDemo1 extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("ServletDemo1運行了");
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
新建一個Filter類,實現Filter接口
重寫doFilter方法
package com.kaigejava.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 MyFilter implements Filter {
@Override
public void destroy() {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
System.out.println("doFilter執行了");
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
}
編輯web.xml,添加filter配置
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xmlns="https://java.sun.com/xml/ns/javaee" xsi:schemaLocation="https://java.sun.com/xml/ns/javaee https://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
<display-name>FilterDemo</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
<filter>
<filter-name>MyFilter</filter-name>
<filter-class>com.anthony.filter.MyFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>MyFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<servlet>
<description></description>
<display-name>ServletDemo1</display-name>
<servlet-name>ServletDemo1</servlet-name>
<servlet-class>com.anthony.servlet.ServletDemo1</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ServletDemo1</servlet-name>
<url-pattern>/servletDemo1</url-pattern>
</servlet-mapping>
</web-app>
運行測試一下
添加到tomcat伺服器管理,啟動服務,瀏覽器訪問下
發現只在控制臺輸出「doFilter執行了「,並沒有執行/servlet/Demo1中的列印語句,這是為什麼呢?
這裡解釋下,我們當前代碼只做了攔截,請求無法往下走,所以servlet中的列印語句沒有輸出,這個時候,如果想要輸出列印語句,就需要放行攔截。具體代碼如下。
package com.kaigjava.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 MyFilter implements Filter {
@Override
public void destroy() {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
System.out.println("doFilter執行了");
// 放行
chain.doFilter(request, response);
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
}
注意上面chain.doFilter(request, response)這行代碼,如果不寫這行,就一直攔截,請求沒法往下走。這個就像我們上面登錄驗證攔截一樣,沒有登錄就沒有放開攔截。
繼續部署上面代碼,再來訪問測試下,控制臺輸出如下內容。
doFilter執行了
ServletDemo1運行了
4.FilterChain
上面我們在web.xml中配置的Filter中過濾url設置是/*,也就是全部請求都進行攔截。在代碼放行中,出現了FilterChain對象,這裡我們簡單來了解下這個過濾鏈對象。
FilterChain是servlet容器為開發任意提供的對象,它提供了對某一資源的已經過濾請求調用鏈的視圖。過濾器使用FilterChain調用鏈中的下一個過濾器。如果調用的過濾器是鏈中的最後一個過濾器,則調用鏈末尾的資源。
怎麼可以形成一個Filter鏈?只要多個Filter對同一個資源進行攔截就可以形成Filter鏈?
怎麼確定Filter的執行順序?由<filter-mapping>中不同Filter寫的先後順序來決定。
這個過濾鏈中不同的Filter過濾先後順序取決於,開發人員在web.xml中的<filter-mapping>寫的先後順序來決定,上面這個圖就是先執行MyFilter這個過濾器,然後再執行MyFilter2這個過濾器.
總結,Filter就處於瀏覽器和伺服器中間的位置,可以攔截任何來自瀏覽器的請求和任意來之伺服器的響應。