Tomcat中Filter過濾器的具體使用
1、Filter 介紹
在 Tomcat 中,F(xiàn)ilter 是一種用于攔截請(qǐng)求和過濾響應(yīng)的組件,可以在請(qǐng)求到達(dá) Servlet 之前或響應(yīng)離開 Servlet 之后對(duì)其進(jìn)行處理。
Filter 的主要應(yīng)用場景包括:
- 權(quán)限控制:可以使用 Filter 來檢查請(qǐng)求的用戶是否具有訪問特定資源的權(quán)限
- 日志記錄:可以使用 Filter 來記錄請(qǐng)求和響應(yīng)的信息,以便進(jìn)行監(jiān)控和故障排除
- 性能監(jiān)控:可以使用 Filter 來測量請(qǐng)求的處理時(shí)間和響應(yīng)時(shí)間,以便進(jìn)行性能優(yōu)化
- 數(shù)據(jù)加密和解密:可以使用 Filter 來對(duì)請(qǐng)求和響應(yīng)進(jìn)行加密和解密,以保護(hù)敏感信息的安全
2、Filter 的生命周期
Filter 的生命周期由 Tomcat 容器管理,包含以下幾個(gè)方法:
- 構(gòu)造器方法,在 web 工程啟動(dòng)的時(shí)候執(zhí)行
- init 初始化方法,在 web 工程啟動(dòng)的時(shí)候執(zhí)行
- doFilter 過濾方法,每次攔截到請(qǐng)求,就會(huì)執(zhí)行
- destroy 銷毀,停止 web 工程的時(shí)候,就會(huì)銷毀 Filter 過濾器
3、Filter 和 FilterChain
Filter 接口
public interface Filter { // 容器創(chuàng)建的時(shí)候調(diào)用, 即啟動(dòng) Tomcat 的時(shí)候調(diào)用 public void init(FilterConfig filterConfig) throws ServletException; // 由 FilterChain 調(diào)用, 并且傳入 FilterChain 本身, 最后回調(diào) FilterChain 的 doFilter() 方法 public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException; // 容器銷毀的時(shí)候調(diào)用, 即關(guān)閉 Tomcat 的時(shí)候調(diào)用 public void destroy(); }
FilterChain 接口
public interface FilterChain { // 由 Filter.doFilter() 中的 chain.doFilter 調(diào)用 public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException; }
當(dāng) Tomcat 接收到 URL 請(qǐng)求時(shí),它會(huì)根據(jù)在 web.xml 文件中配置的過濾器和映射路徑來創(chuàng)建 FilterChain。如果某個(gè)請(qǐng)求匹配了一些過濾器的映射路徑,那么這些過濾器將被添加到 FilterChain。創(chuàng)建了 FilterChain 之后,就開始執(zhí)行 doFilter,進(jìn)行請(qǐng)求的鏈?zhǔn)教幚怼?/p>
過濾器執(zhí)行順序:
- 通過 web.xml 配置的 Filter 過濾器,執(zhí)行順序由 <filter-mapping> 標(biāo)簽的配置順序決定。<filter-mapping> 靠前,則 Filter 先執(zhí)行,靠后則后執(zhí)行。通過修改 <filter-mapping> 的順序便可以修改 Filter 的執(zhí)行順序
- 通過 @WebFilter 注解配置的 Filter 過濾器,無法進(jìn)行排序,若需要對(duì) Filter 過濾器進(jìn)行排序,建議使用 web.xml 進(jìn)行配置
4、Filter 攔截過程
如圖是 Filter 攔截過程示意圖。所有 Filter 和 Web 資源都默認(rèn)執(zhí)行在同一個(gè)線程中(因?yàn)镕ilter 和 Web 資源通常是在 HttpServlet 容器中運(yùn)行的,而 HttpServlet 容器是基于單線程模型的)。對(duì)于 FilterChain 中的 Filter,它們都使用同一 Request 對(duì)象。
以下是 Filter 攔截過程的一般步驟:
- 客戶端發(fā)送請(qǐng)求到給 Web 服務(wù)器
- Web 服務(wù)器接收到請(qǐng)求后,將請(qǐng)求傳遞給 HttpServlet 容器
- HttpServlet 容器根據(jù)請(qǐng)求的 URL 路徑和配置的映射信息,確定應(yīng)該調(diào)用哪些 Filter
- Filter 的 doFilter() 方法被調(diào)用,該方法將接收請(qǐng)求和響應(yīng)對(duì)象作為參數(shù)
- 在 doFilter() 方法中,F(xiàn)ilter 可以執(zhí)行各種操作,例如檢查請(qǐng)求頭、修改請(qǐng)求參數(shù)、處理權(quán)限驗(yàn)證等
- 如果 Filter 決定繼續(xù)處理請(qǐng)求,它可以通過調(diào)用 filterChain.doFilter() 方法將請(qǐng)求傳遞給下一個(gè) Filter(如果有下一個(gè) Filter)或 Web 資源(沒有下一個(gè) Filter)
- 下一個(gè) Filter 的 doFilter() 方法被調(diào)用,直到請(qǐng)求到達(dá)最終的目標(biāo)資源
- 目標(biāo)資源處理請(qǐng)求并生成響應(yīng),響應(yīng)通過 Filter 鏈反向傳遞,每個(gè) Filter 都可以在響應(yīng)離開之前對(duì)其進(jìn)行修改或處理
- 最終,響應(yīng)被發(fā)送回客戶端,客戶端接收到處理后的結(jié)果
5、FilterConfig
FilterConfig 是 Filter 過濾器的配置文件類。Tomcat 每次創(chuàng)建 Filter 的時(shí)候,也會(huì)同時(shí)創(chuàng)建一個(gè) FilterConfig 類,它包含了 Filter 配置文件的配置信息。
FilterConfig 類的作用是獲取 filter 過濾器的配置內(nèi)容
- 獲取 Filter 的名稱 filter-name 的內(nèi)容
- 獲取在 Filter 中配置的 init-param 初始化參數(shù)
- 獲取 ServletContext 對(duì)象
@Override public void init(FilterConfig filterConfig) throws ServletException { // 1、獲取 Filter 的名稱 filter-name 的內(nèi)容 System.out.println("filter-name 的值是:" + filterConfig.getFilterName()); // 2、獲取在 web.xml 中配置的 init-param 初始化參數(shù) System.out.println("初始化參數(shù) username 的值是:" + filterConfig.getInitParameter("username")); System.out.println("初始化參數(shù) url 的值是:" + filterConfig.getInitParameter("url")); // 3、獲取 ServletContext 對(duì)象 System.out.println(filterConfig.getServletContext()); }
6、Filter 使用
工程目錄
web.xml 配置
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" version="4.0"> <!-- <display-name> 元素常用于配置 servlet、過濾器或其他 Web 組件的顯示名稱。 這個(gè)顯示名稱主要用于在管理界面或日志中標(biāo)識(shí)該組件,以方便識(shí)別和管理。 --> <!-- 標(biāo)識(shí)項(xiàng)目名 --> <display-name>ServletTest</display-name> <!-- 定義首頁文件,也就是用戶直接輸入域名時(shí)跳轉(zhuǎn)的頁面(如http://localhost:8080/)--> <welcome-file-list> <welcome-file>login.jsp</welcome-file> </welcome-file-list> <!--filter 標(biāo)簽用于配置一個(gè) Filter 過濾器--> <filter> <!--給 filter 起一個(gè)別名--> <filter-name>AdminFilter1</filter-name> <!--配置 filter 的全類名--> <filter-class>com.test.AdminFilter1</filter-class> <!-- 設(shè)置 Servlet 初始化參數(shù) 可以通過 FilterConfig.getInitParamenter(String name) 方法訪問初始化參數(shù) --> <init-param> <param-name>username</param-name> <param-value>root</param-value> </init-param> <init-param> <param-name>url</param-name> <param-value>jdbc:mysql://localhost3306/test</param-value> </init-param> </filter> <!-- 設(shè)置 filter 映射 --> <filter-mapping> <!-- 和 filter 標(biāo)簽中的 filter-name 對(duì)應(yīng) --> <filter-name>AdminFilter1</filter-name> <!-- 設(shè)置匹配的路徑,這里設(shè)置為 /img/* 表示訪問 img 目錄下的圖片都會(huì)調(diào)用該 filter(AdminFilter) --> <url-pattern>/img/*</url-pattern> </filter-mapping> <filter> <filter-name>AdminFilter2</filter-name> <filter-class>com.test.AdminFilter2</filter-class> </filter> <filter-mapping> <filter-name>AdminFilter2</filter-name> <url-pattern>/img/*</url-pattern> </filter-mapping> </web-app>
login.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>登錄</title> </head> <body> <form action="http://localhost:8080/servlettest/loginServlet" method="get"> 用戶名: <input type="text" name="username"/> <br> 密 碼: <input type="password" name="password"/> <br> <input type="submit" /> </form> </body> </html>
LoginServlet 類
package com.test; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; @WebServlet("/loginServlet") public class LoginServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setContentType("text/html; charset=UTF-8"); String username = req.getParameter("username"); String password = req.getParameter("password"); if ("root".equals(username) && "123456".equals(password)) { System.out.println("設(shè)置 Seesion: {user : " + username + " }"); req.getSession().setAttribute("user",username); System.out.println("登錄成功!"); resp.getWriter().write("登錄 成功?。。?); } else { System.out.println("登錄失??!"); req.getRequestDispatcher("/login.jsp").forward(req,resp); } } }
AdminFilter1 類
package com.test; import javax.servlet.*; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; import java.io.IOException; public class AdminFilter1 implements Filter { // doFilter 方法,專門用于攔截請(qǐng)求??梢宰鰴?quán)限檢查 @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { System.out.println("過濾器 AdminFilter1"); HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest; HttpSession session = httpServletRequest.getSession(); Object user = session.getAttribute("user"); // System.out.println("登錄用戶: " + user); // 如果等于 null,說明還沒有登錄 if (user == null) { System.out.println("未登錄,跳轉(zhuǎn)到登錄頁面"); servletRequest.getRequestDispatcher("/login.jsp").forward(servletRequest,servletResponse); return; } else { // 讓程序繼續(xù)往下訪問用戶的目標(biāo)資源 System.out.println("AdminFilter1 調(diào)用 doFilter 方法"); filterChain.doFilter(servletRequest,servletResponse); System.out.println("AdminFilter1 結(jié)束了 doFilter 方法的調(diào)用"); } } @Override public void init(FilterConfig filterConfig) throws ServletException { // 1、獲取 Filter 的名稱 filter-name 的內(nèi)容 System.out.println("filter-name 的值是:" + filterConfig.getFilterName()); // 2、獲取在 web.xml 中配置的 init-param 初始化參數(shù) System.out.println("初始化參數(shù) username 的值是:" + filterConfig.getInitParameter("username")); System.out.println("初始化參數(shù) url 的值是:" + filterConfig.getInitParameter("url")); // 3、獲取 ServletContext 對(duì)象 System.out.println(filterConfig.getServletContext()); } }
AdminFilter2 類
package com.test; import javax.servlet.*; import java.io.IOException; public class AdminFilter2 implements Filter { // doFilter 方法,專門用于攔截請(qǐng)求??梢宰鰴?quán)限檢查 @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { System.out.println("過濾器 AdminFilter2"); System.out.println("AdminFilter2 調(diào)用 doFilter 方法"); filterChain.doFilter(servletRequest,servletResponse); System.out.println("AdminFilter2 結(jié)束了 doFilter 方法的調(diào)用"); } }
運(yùn)行演示圖
運(yùn)行流程:
- 啟動(dòng)服務(wù)器 Tomcat,創(chuàng)建 AdminFilter1 和 AdminFilter2 對(duì)象,獲取 FilterConfig 配置并初始化,創(chuàng)建 LoginServlet 對(duì)象,獲取 ServletConfig 配置并初始化,進(jìn)入首頁文件 login.jsp
- 客戶端嘗試請(qǐng)求訪問 http://localhost:8080/servlettest/img/2.jpg,由過濾器 AdminFilter1 處理,輸出“過濾器 AdminFilter1”和“未登錄,跳轉(zhuǎn)到登錄頁面”,之后跳轉(zhuǎn)到 login.jsp 進(jìn)行登錄
- 輸入賬號(hào):root,密碼:123456,由 LoginServlet 的 doGet() 方法處理,設(shè)置 Seesion: {user : root },輸出“登錄成功!”
- 客戶端再次請(qǐng)求訪問 http://localhost:8080/servlettest/img/2.jpg,由過濾器 AdminFilter1 和 AdminFilter2 依次處理(調(diào)用 filterChain.doFilter 方法后可以對(duì)響應(yīng)結(jié)果進(jìn)行處理),之后返回響應(yīng)結(jié)果給客戶端
- 客戶端得到響應(yīng)結(jié)果,顯示圖片
到此這篇關(guān)于Tomcat中Filter過濾器的具體使用的文章就介紹到這了,更多相關(guān)Tomcat Filter過濾器內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
關(guān)于 Tomcat進(jìn)程意外退出的問題解析
這篇文章主要介紹了關(guān)于 Tomcat進(jìn)程意外退出的問題解析的相關(guān)資料,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2016-11-11TOMCAT啟動(dòng)失敗using?catalina_opts為空的解決方法
這篇文章主要給大家分享了TOMCAT啟動(dòng)失敗using?catalina_opts為空的解決方法,文中有詳細(xì)的解決流程,具有一定的參考價(jià)值,需要的朋友可以參考下2023-10-10idea專業(yè)版和idea社區(qū)版整合Tomcat并將war包部署
IDEA是一個(gè)功能完善的Java開發(fā)工具,除了具備有良好的代碼開發(fā)提示之外,還可以直接在IDEA中集成并啟動(dòng)Tomcat實(shí)現(xiàn)程序的自動(dòng)部署,本文主要介紹了idea專業(yè)版和idea社區(qū)版整合Tomcat并將war包部署,感興趣的可以了解一下2023-11-11tomcat+nginx實(shí)現(xiàn)多應(yīng)用部署的示例代碼
本文主要介紹了tomcat+nginx實(shí)現(xiàn)多應(yīng)用部署的示例代碼,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-11-11tomcat相關(guān)配置與eclipse集成_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
這篇文章主要介紹了tomcat相關(guān)配置與eclipse集成_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理的相關(guān)資料,需要的朋友可以參考下2017-07-07tomcat7w.exe 出現(xiàn)指定的服務(wù)未安裝的解決方法
下面小編就為大家分享一篇tomcat7w.exe 出現(xiàn)指定的服務(wù)未安裝的解決方法,很簡單,有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2017-11-11