springMVC04-Filter過濾器與攔截器

一、Filter(過濾器)和 Interceptor(攔截器)

在 SpringMVC 中,Filter(過濾器)和 Interceptor(攔截器)都是請求響應進行預處理后處理的重要工具,但它們存在本質區別,屬于不同層面的機制:


1-1、Filter(過濾器)

  • 屬于 Servlet 規范的一部分

  • 和 Spring 無關,作用于整個 Web 應用(包括靜態資源、Servlet、SpringMVC 控制器等)

  • 是在 SpringMVC 前進行處理的。

1、使用場景:

  • 編碼處理(如統一設置 request 編碼)

  • 權限校驗、登錄驗證(不依賴 Spring Bean)

  • 請求日志記錄

  • XSS 防護、跨域設置

2、編寫方式:

@WebFilter(urlPatterns = "/*")  // 或在 web.xml 中配置
public class MyFilter implements Filter {@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)throws IOException, ServletException {System.out.println("Filter: 請求前...");chain.doFilter(request, response); // 放行System.out.println("Filter: 響應后...");}
}

3、特點總結:

  • 生命周期由 Servlet 容器管理

  • DispatcherServlet(SpringMVC 核心)之前執行

  • 無法使用 Spring 的依賴注入(因為不是 Spring Bean)


1-2、Interceptor(攔截器)

  • 是 SpringMVC 提供的機制

  • 只會攔截進入 DispatcherServlet 的請求(也就是經過 SpringMVC 控制器的)

  • 屬于 Spring 容器管理,可以使用依賴注入

1、使用場景:

  • 控制器權限校驗(如登錄檢查)

  • 日志記錄、性能分析

  • 國際化、視圖數據填充

  • API 接口簽名校驗等

2、編寫方式:

(1). 實現 HandlerInterceptor 接口:
public class MyInterceptor implements HandlerInterceptor {// 請求前@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)throws Exception {System.out.println("Interceptor: 控制器前");return true; // false 則中斷執行}// 控制器執行后,視圖渲染前@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response,Object handler, ModelAndView modelAndView) throws Exception {System.out.println("Interceptor: 控制器后");}// 完全結束后(包括視圖渲染)@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response,Object handler, Exception ex) throws Exception {System.out.println("Interceptor: 完成后");}
}

(2). 注冊攔截器(Java 配置方式):
@Configuration
public class WebConfig implements WebMvcConfigurer {@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new MyInterceptor()).addPathPatterns("/**").excludePathPatterns("/login", "/static/**");}
}

3、特點總結:

  • 生命周期由 Spring 管理,可注入 Bean

  • 只攔截 Controller 請求,靜態資源不會被攔截

  • 更適合業務層邏輯(如認證授權、日志記錄等)


1-3、兩者對比總結:

對比項FilterInterceptor
所屬規范Servlet 規范Spring 框架
攔截范圍所有請求(靜態資源、Servlet)只攔截 SpringMVC 控制器請求
執行時機DispatcherServlet 之前DispatcherServlet 之后
配置方式@WebFilterweb.xml實現 HandlerInterceptor 接口
注入 Spring Bean
控制執行流程不能直接終止控制器方法執行可以通過 preHandle 控制是否繼續

1-4、實際建議:

  • Filter: 用于與 Spring 無關的通用功能(如編碼、日志、跨域等)

  • Interceptor: 用于控制器相關的邏輯(如登錄校驗、權限控制)

如果你只是處理 SpringMVC 控制器請求,推薦使用 Interceptor,它更靈活、易于與 Spring 的其他功能結合使用。


二、攔截器的執行流程圖

瀏覽器請求在 SpringMVC 中的執行順序:

1. 瀏覽器發送請求(HTTP 請求)
↓
2. Filter.doFilter()(過濾器處理)
↓
3. DispatcherServlet.doDispatch()↓3.1 調用 HandlerInterceptor.preHandle()(前置攔截器)↓
4. Controller 方法執行(處理業務邏輯)
↓
5. HandlerInterceptor.postHandle()(后置攔截器:控制器執行后,視圖渲染前)
↓
6. 視圖解析與渲染(如返回 Thymeleaf、JSP、JSON 等)
↓
7. HandlerInterceptor.afterCompletion()(請求完成后,清理資源)
↓
8. Filter.doFilter() 后處理部分繼續執行(回到過濾器的“響應后”部分)
↓
9. 響應返回給瀏覽器
階段處理組件方法說明
1FilterdoFilter(request, response)最先執行的組件(如編碼設置、日志)
2DispatcherServletdoDispatch()SpringMVC 核心分發器
3InterceptorpreHandle()在 Controller 前執行,可中斷流程
4Controller處理請求的方法(比如 @GetMapping執行業務邏輯
5InterceptorpostHandle()Controller 執行后,視圖渲染前
6視圖解析渲染返回的頁面或 JSON渲染 View、封裝 Model
7InterceptorafterCompletion()整個請求執行完,做資源清理、異常處理等
8FilterdoFilter 后段Filter 的“響應后”邏輯
9瀏覽器展示響應結果最終結果返回給用戶

三、攔截器的配置

SpringMVC中的攔截器用于攔截控制器方法的執行

SpringMVC中的攔截器需要實現HandlerInterceptor接口;或者繼承HandlerInterceptorAdapter類(已過時)

SpringMVC的攔截器必須在SpringMVC的配置文件中進行配置:

3-1、步驟一:編寫一個類,實現handerInterceptor接口

public class MyInterceptor implements HandlerInterceptor {// 前置處理(Controller方法調用前)@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)throws Exception {System.out.println("前置處理:preHandle");return true; // 返回true才會繼續調用后面的攔截器或Controller}// 后置處理(Controller方法調用后,但視圖未渲染前)@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response,Object handler, ModelAndView modelAndView) throws Exception {System.out.println("后置處理:postHandle");}// 完成后處理(視圖渲染后,一般用于資源清理)@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response,Object handler, Exception ex) throws Exception {System.out.println("最終處理:afterCompletion");}
}

重寫里面的三個方法:

  • preHandle
  • postHandle
  • afterCompletion(渲染視圖之后)

3-2、在springMVC.xml中配置攔截器

1、配置方式一:bean

    <!-- 配置攔截器 --><mvc:interceptors><bean class="com.wsbazinga.controller.MyInterceptorController"></bean></mvc:interceptors>

頁面返回值:

2、配置方式二:ref

    <!-- 配置攔截器 --><mvc:interceptors><!--<bean class="com.wsbazinga.controller.MyInterceptor"></bean>--><ref bean="myInterceptor"></ref></mvc:interceptors>

【注意】:

此時,攔截器類:MyInterceptor,要加上@Component注解,才能被IOC容器注入,并配置在ref中!

?

【注意】:

方式一,方式二,所有的請求都會被攔截!?

3、配置方式三:可以指定攔截

<!-- 配置攔截器 -->
<mvc:interceptors><mvc:interceptor><mvc:mapping path="/**"/> <!-- 攔截所有路徑 --><mvc:exclude-mapping path="/login"/> <!-- 排除攔截的url --><bean class="com.example.interceptor.MyInterceptor"/></mvc:interceptor>
</mvc:interceptors>

?【注意】:

攔截器和過濾器不同,攔截所有請求用的是:/**,而不是/*!

4、使用 Java 配置類(推薦,Spring Boot/Spring 5 常用)

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;@Configuration
public class WebConfig implements WebMvcConfigurer {@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new MyInterceptor()).addPathPatterns("/**")                // 攔截所有請求.excludePathPatterns("/login", "/css/**", "/js/**"); // 放行登錄、靜態資源}
}

?

四、多個攔截器的執行順序

在 SpringMVC 中使用 多個攔截器 時,它們的執行順序由你在配置時的注冊順序決定,就像“攔截器棧”。

4-1、多個攔截器的preHandle()都返回true

假設你注冊了兩個攔截器:

@Override
public void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new FirstInterceptor()).addPathPatterns("/**");registry.addInterceptor(new SecondInterceptor()).addPathPatterns("/**");
}

那么執行順序是:

方法名執行順序
preHandle()先注冊的先執行:First → Second(順序)
postHandle()先注冊的后執行:Second → First(倒序)
afterCompletion()先注冊的后執行:Second → First(倒序)

示例:假設兩個攔截器打印日志

public class FirstInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(...) {System.out.println("First - preHandle");return true;}@Overridepublic void postHandle(...) {System.out.println("First - postHandle");}@Overridepublic void afterCompletion(...) {System.out.println("First - afterCompletion");}
}public class SecondInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(...) {System.out.println("Second - preHandle");return true;}@Overridepublic void postHandle(...) {System.out.println("Second - postHandle");}@Overridepublic void afterCompletion(...) {System.out.println("Second - afterCompletion");}
}

輸出結果將是:

First - preHandle
Second - preHandle
Second - postHandle
First - postHandle
Second - afterCompletion
First - afterCompletion

?總結:

方法順序說明
preHandle()注冊順序執行(1 → 2 → 3)
postHandle()注冊反向順序(3 → 2 → 1)
afterCompletion()注冊反向順序(3 → 2 → 1)
如果中斷請求后續 preHandle() 不執行,已執行的 afterCompletion() 執行

4-2、多個攔截器中,有一個攔截器的 preHandle() 返回了 false?

1、后續攔截器的 preHandle() 不會再執行

  • 攔截鏈中斷,SpringMVC 不會再往下調用后面的攔截器或 Controller 方法。


2、Controller 方法 不會被執行

  • SpringMVC 直接終止請求流程,不會進入控制器。


3、已成功通過的攔截器(即 preHandle() 返回 true)的afterCompletion() 仍然會執行

  • SpringMVC 會把之前已經通過的攔截器的 afterCompletion() 方法 按反順序執行,用于清理資源。


示例:

假設我們注冊了 3 個攔截器,順序如下:

registry.addInterceptor(new Interceptor1());
registry.addInterceptor(new Interceptor2());
registry.addInterceptor(new Interceptor3());

攔截器2 的 preHandle() 返回 false

public class Interceptor2 implements HandlerInterceptor {@Overridepublic boolean preHandle(...) {System.out.println("Interceptor2 - preHandle");return false; // 攔截住!}@Overridepublic void afterCompletion(...) {System.out.println("Interceptor2 - afterCompletion");}
}

打印結果將是:

Interceptor1 - preHandle
Interceptor2 - preHandle  (返回 false,終止)
Interceptor1 - afterCompletion

注意:

  • Interceptor3 的任何方法都不會執行!

  • postHandle() 都不會執行!因為 Controller 都沒進去!

  • afterCompletion() 只對 已成功通過的攔截器(即 preHandle() 返回 true) 調用

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/88296.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/88296.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/88296.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

STM32第十九天 ESP8266-01S和電腦實現串口通信(2)

1&#xff1a;UDP 傳輸UDP 傳輸不不區分 server 或者 client &#xff0c;由指令 ATCIPSTART 建?立傳輸。 1. 配置 WiFi 模式 ATCWMODE3 // softAPstation mode 響應 : OK 2. 連接路路由器? ATCWJAP"SSID","password" // SSID and password of router 響…

大健康IP如何用合規運營打破“信任危機”|創客匠人

一、行業亂象下的信任裂痕當前大健康領域私域直播亂象頻發&#xff0c;部分機構利用“假專家義診”“限量搶購”等話術&#xff0c;將低成本保健品高價賣給老人&#xff0c;甚至有技術公司提供“全鏈路坑老方案”&#xff0c;加劇行業信任危機。這種短視行為不僅損害消費者權益…

MySQL(122)如何解決慢查詢問題?

解決慢查詢問題通常涉及到多種技術和方法&#xff0c;以確保數據庫查詢的高效性和響應速度。以下是詳細步驟和示例代碼&#xff0c;闡述如何解決慢查詢問題。 一. 慢查詢的常見原因 缺少索引&#xff1a;查詢未使用索引或索引未優化。查詢不當&#xff1a;查詢語句本身書寫不合…

esp32在vscode中仿真調試

此方法可以用在具有usb serial jtag功能的esp32芯片用&#xff0c;支持型號&#xff1a; ESP32-C3 ESP32-S3 ESP32-C6 ESP32-H2 ESP32-C5 USB Serial JTAG功能介紹&#xff1a; 從硬件角度&#xff1a; 它是ESP32芯片內置的硬件功能 不是一個獨立的物理接口 是通過USB接口實…

藍橋云課 矩形切割-Java

目錄 題目鏈接 題目 解題思路 代碼 題目鏈接 競賽中心 - 藍橋云課 題目 解題思路 找最大的正方形就是大邊-n個小邊&#xff0c;直至相等或者小于1 代碼 import java.util.Scanner; // 1:無需package // 2: 類名必須Main, 不可修改public class Main {public static voi…

PostgreSQL 鎖等待監控,查找等待中的鎖

直接貼SQLWITH RECURSIVE l AS (SELECT pid, locktype, mode, granted, ROW(locktype,database,relation,page,tuple,virtualxid,transactionid,classid,objid,objsubid) objFROM pg_locks ), pairs AS (SELECT w.pid waiter, l.pid locker, l.obj, l.modeFROM l wJOIN l ON l.…

Elasticsearch 字符串包含子字符串:高級查詢技巧

作者&#xff1a;來自 Elastic Justin Castilla 想要獲得 Elastic 認證&#xff1f;看看下一次 Elasticsearch Engineer 培訓什么時候開始吧&#xff01; Elasticsearch 擁有大量新功能&#xff0c;可以幫助你為你的使用場景構建最佳的搜索解決方案。深入了解我們的示例 noteb…

Vue、Laravel 項目初始化命令對比 / curl 命令/ CORS 機制總結與案例

前言一個疑問衍生出另一個疑問再衍生出又一個疑問&#xff0c;于是有了這篇文章。一、Vue 項目初始化命令 基于 Vite 創建 Vue 項目 命令&#xff1a;npm create vitelatest my-project -- --template vue適用場景&#xff1a;需輕量級、高速開發環境關鍵點&#xff1a;使用 Vi…

Jenkins 流水線配置

Jenkinsfile dsl文件:pipeline {// 指定任務在哪個集群節點執行agent any// 聲明全局變量environment {keyvalueAPPLICATION_NAMEspringboot-demo // 項目名稱HOST_PORT7777 // 宿主機暴露服務端口CONTAINER_PORT8080 // 容器內部服務端口…

服務器重裝后如何“復活”舊硬盤上的 Anaconda 環境?—— 一次完整的排錯與恢復記錄

目錄 摘要 一、 背景&#xff1a;熟悉的陌生人 二、 問題浮現&#xff1a;一次次失敗的嘗試 問題一&#xff1a;source activate 失效&#xff0c;被寫死的舊路徑 問題二&#xff1a;官方安裝器修復失敗&#xff0c;神秘的“進程池損壞” 問題三&#xff1a;核心腳本也“背…

Redis的多并發實際業務場景下的使用分析:布隆過濾器

文章目錄前言什么是布隆過濾器項目中引入布隆過濾器與緩存結合的最佳實踐場景&#xff1a;高并發用戶訪問商品詳情頁&#xff08;防止緩存穿透&#xff09;總結&#xff1a;前言 okok 我們已經學完了 所有的redis中的常用的數據結構 下面就是進階 我會用一系列的例子 去講解 如…

【AI】人工智能領域關鍵術語全解析

一、前言 人工智能&#xff08;AI&#xff09;作為當今最熱門的技術領域之一&#xff0c;正在深刻改變著我們的生活和工作方式。然而&#xff0c;對于初學者或非技術背景的人士來說&#xff0c;理解AI領域的專業術語可能是一項挑戰。本文旨在全面解析人工智能領域的關鍵術語&a…

【Linux基礎知識系列】第四十三篇 - 基礎正則表達式與 grep/sed

在Linux系統中&#xff0c;正則表達式是一種強大的文本處理工具&#xff0c;廣泛用于文本搜索、替換和批量處理。通過掌握基礎正則表達式的語法&#xff0c;結合grep和sed命令&#xff0c;用戶可以高效地完成復雜的文本處理任務。無論是數據分析師、軟件開發者還是系統管理員&a…

SIMATIC S7-1200的以太網通信能力:協議與資源詳細解析

SIMATIC S7-1200的以太網通信能力&#xff1a;協議與資源解析 在工業自動化領域&#xff0c;PLC的通信能力往往直接影響著整個控制系統的靈活性與高效性。西門子SIMATIC S7-1200系列PLC作為一款廣泛應用的中小型控制器&#xff0c;其強大的以太網通信功能是其核心優勢之一。本文…

什么是高防 IP?從技術原理到實戰部署的深度解析

目錄 前言 一、高防 IP 的定義與核心價值 二、高防 IP 的技術原理與架構 2.1 流量牽引技術 2.2 流量清洗引擎 2.3 回源機制 三、高防 IP 的核心防護技術詳解 3.1 DDoS 攻擊防御技術 3.2 高防 IP 的彈性帶寬設計 四、實戰&#xff1a;基于 Linux 的高防 IP 環境配置 …

NW710NW713美光固態閃存NW719NW720

美光NW系列固態閃存深度解析&#xff1a;技術、性能與市場洞察一、技術架構與核心創新美光NW系列固態閃存&#xff08;包括NW710、NW713、NW719、NW720&#xff09;的技術根基源于其先進的G9 NAND架構。該架構通過5納米制程工藝和多層3D堆疊技術&#xff0c;在單位面積內實現了…

JVM匯總

1.什么是JVM&#xff1f;Java虛擬機&#xff0c;Java具有自動內存管理等一系列特性&#xff0c;為實現Java跨平臺&#xff0c;一次編譯處處執行。2.JVM結構圖3.類加載器-入口加載class文件&#xff0c;將類信息存放到運行時數據區的方法區內存空間中通過魔數和文件格式來判斷是…

2024.09.20 leetcode刷題記錄

# 前言 昨天發布了第一遍博客&#xff0c;感覺很好&#xff0c;趁著我現在還是很感興趣就多發幾遍&#xff0c;希望能堅持下去&#xff0c;在這里記錄下自己學習成長的經歷。 今天是周五&#xff0c;下周一就又要去實習啦&#xff0c;距離上一段實習剛結束一個月&#xff0c;之…

SQLite3 中列(變量)的特殊屬性

在 SQLite3 中&#xff0c;列的特殊屬性通常通過約束&#xff08;Constraints&#xff09;和數據類型修飾符來定義。這些屬性可以在創建表時指定&#xff0c;用于限制數據的完整性或定義特殊行為。以下是 SQLite3 支持的主要特殊屬性及其說明&#xff1a; 1. 主鍵約束&#xff…

Datawhale AI 夏令營:用戶洞察挑戰賽 Notebook(2)

針對文本聚類優化 優化TF-IDF特征工程# 調整ngram_range&#xff1a;設置為(1, 2)&#xff0c;捕捉單字和雙字詞&#xff08;如“不錯”“不滿意”&#xff09;。 # 限制特征數量&#xff1a;通過max_features5000保留高信息密度特征&#xff0c;降低維度。 # 過濾低頻/高頻詞&…