最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Spring?Boot?Interceptor的原理、配置、順序控制及與Filter的關(guān)鍵區(qū)別對比分析

 更新時間:2025年12月04日 11:34:00   作者:ArabySide  
本文主要介紹了Spring?Boot中的攔截器(Interceptor)及其與過濾器(Filter)的區(qū)別,攔截器是Spring?MVC提供的接口,可以實現(xiàn)請求處理前后的邏輯,本文介紹的非常詳細,感興趣的朋友跟隨小編一起看看吧

前言

Spring Boot 中,攔截器通常用于在請求處理前后執(zhí)行一些邏輯,這點與Servlet容器提供的過濾器有點類似。平常我們開發(fā)Jave Web應(yīng)用的時候,經(jīng)常能碰到要對請求訪問進行通用邏輯處理的場景,比方說記錄訪問日志、確認訪問權(quán)限等。你是否曾經(jīng)糾結(jié)于是選過濾器還是攔截器來實現(xiàn)邏輯代碼的編寫,本篇文章先重點介紹Spring中的interceptor攔截器, 然后就過濾器和攔截器這兩個常見但易混淆的請求攔截工具,討論兩者相似且不同之處。

關(guān)于過濾器的內(nèi)容在這篇里有詳細介紹鏈接: 【Java Web】過濾器的核心原理、實現(xiàn)與執(zhí)行順序配置

一、核心功能

Interceptor的核心能力來自于HandlerInterceptor這個接口,這是Spring MVC提供的接口。接口主要包含三個待實現(xiàn)的方法,preHandle(),postHandle()和afterCompletion()。

  • preHandle() :在Controller方法執(zhí)行前調(diào)用,返回 false 會中斷請求。攔截器最常見實現(xiàn)的方法,一般用來做權(quán)限校驗、參數(shù)預(yù)處理等。
  • postHandle():Controller 執(zhí)行完但視圖未渲染前調(diào)用,一般用于修改ModelAndView,比如添加一些通用的響應(yīng)頭或修改返回數(shù)據(jù)。
  • afterCompletion():整個請求完成后調(diào)用,可以用來記錄日志。

通過這三個方法,就能賦予我們對于Controller層的精細化的控制。如果是WebApi這種項目忽略postHandle方法。

方法里包含各類參數(shù),比如都包含HttpServletRequest和HttpServletResponse變量,用于獲取和設(shè)置讀取請求數(shù)據(jù)和響應(yīng)輸出。preHandle() 和postHandle()方法的handler參數(shù)代表當(dāng)前 HTTP 請求所匹配的處理器對象,是一個封裝了Controller方法的對象、所屬類、參數(shù)、注解等詳細信息的類。postHandle()的modelAndView 則是處理器方法執(zhí)行完成后返回的模型視圖對象。最后afterCompletion方法的可空的Exception參數(shù),如果方法運行出現(xiàn)錯誤了,那么這個參數(shù)就包含具體的異常信息。

Interceptor本質(zhì)上是就是對Controller層的控制。執(zhí)行順序是preHandle => Controller => postHandle => afterCompletion

完整接口

package org.springframework.web.servlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.lang.Nullable;
import org.springframework.web.method.HandlerMethod;
public interface HandlerInterceptor {
	default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {
		return true;
	}
	default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
			@Nullable ModelAndView modelAndView) throws Exception {
	}
	default void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,
			@Nullable Exception ex) throws Exception {
	}
}

二、攔截器的實現(xiàn)

2.1 定義自定義攔截器

實現(xiàn)攔截器需要定義一個類來實現(xiàn)Interceptor接口,比如我要實現(xiàn)一個驗證Jwt的攔截器,編寫一個類實現(xiàn)Interceptor接口,并且我們在類上用@Component注解修飾,將其當(dāng)作一個bean對象方便下一步注冊。由于Jwt攔截器只需要在請求前進行邏輯驗證,這里就只重載preHandle方法。

在preHandle方法里,如果返回值是false,那么后續(xù)Controller里的Handler Method是不會執(zhí)行的,只有返回值是true,后續(xù)的Controller才會執(zhí)行。

package org.araby.blognovelink.interceptor;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.araby.blognovelink.utils.JwtUtils;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
@Component
@Slf4j
public class TokenInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String originToken = request.getHeader("Authorization");
        if (originToken == null || originToken.isEmpty()){
            log.info("未登錄");
            response.setStatus(401);
            return false;
        }
        String[] parts = originToken.split(" ");
        if (parts.length != 2 || !"Bearer".equalsIgnoreCase(parts[0])) {
            log.info("Token格式錯誤");
            response.setStatus(401);
            return false;
        }
        String token = parts[1];
        if (token == null || token.isEmpty()){
            log.info("未登錄");
            response.setStatus(401);
            return false;
        }
        try {
            JwtUtils.pareseToken(token);
        }
        catch (Exception e){
            log.info("登錄失敗");
            response.setStatus(401);
            return false;
        }
        log.info("登錄成功");
        return true;
    }
}

2.2 注冊攔截器

注冊攔截器需要定義一個配置類實現(xiàn)WebMvcConfigurer接口。最為關(guān)鍵的是通過addInterceptors重載方法,將我們自定義的攔截器通過添加到InterceptorRegistry中。

registry.addInterceptor()的方法參數(shù)便是我們的攔截器,我們還可以在后面通過鏈?zhǔn)秸{(diào)用添加addPathPatterns【攔截器匹配路徑】和excludePathPatterns【排除路徑】

@Configuration
public class WebConfig implements WebMvcConfigurer {
    private final TokenInterceptor tokenInterceptor;
    @Autowired
    public WebConfig(TokenInterceptor tokenInterceptor) {
        this.tokenInterceptor = tokenInterceptor;
    }
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(tokenInterceptor).addPathPatterns("/**").excludePathPatterns("/login/**");
    }
}

三、多攔截器的執(zhí)行順序

前面在介紹注冊攔截器的時候我們提到過registry.addInterceptor()這個方法,其實它后面還能通過鏈?zhǔn)秸{(diào)用添加進行設(shè)置order(),方法內(nèi)可以添加參數(shù),越小越先執(zhí)行。

若未顯式設(shè)置 order,攔截器執(zhí)行順序為注冊順序,也就是registry.addInterceptor的先后

下面我這次三個攔截器,并且讓CInterceptor的順序最靠前,其實BInterceptor ,最后AInterceptor,并觀察執(zhí)行日志。

@Configuration
public class WebConfig implements WebMvcConfigurer {
    private final TokenInterceptor tokenInterceptor;
    private final AInterceptor aInterceptor;
    private final BInterceptor bInterceptor;
    private final CInterceptor cInterceptor;
    @Autowired
    public WebConfig(TokenInterceptor tokenInterceptor, AInterceptor aInterceptor, BInterceptor bInterceptor, CInterceptor cInterceptor) {
        this.tokenInterceptor = tokenInterceptor;
        this.aInterceptor = aInterceptor;
        this.bInterceptor = bInterceptor;
        this.cInterceptor = cInterceptor;
    }
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        //registry.addInterceptor(tokenInterceptor).addPathPatterns("/**").excludePathPatterns("/login/**");
        registry.addInterceptor(aInterceptor).addPathPatterns("/**").order(3);
        registry.addInterceptor(bInterceptor).addPathPatterns("/**").order(2);
        registry.addInterceptor(cInterceptor).addPathPatterns("/**").order(1);
    }
}

打印日志很有意思,preHandle方法按照order的順序是C-B-A,但是postHandle和afterCompletion是按照A-B-C。

[INFO ] [2025-12-03 23:03:11.669] [http-nio-9090-exec-2] [REQ-715ada0abaf74a959414802237aaa5c4] o.a.b.interceptor.CInterceptor - CInterceptor preHandle
[INFO ] [2025-12-03 23:03:11.669] [http-nio-9090-exec-2] [REQ-715ada0abaf74a959414802237aaa5c4] o.a.b.interceptor.BInterceptor - BInterceptor preHandle
[INFO ] [2025-12-03 23:03:11.669] [http-nio-9090-exec-2] [REQ-715ada0abaf74a959414802237aaa5c4] o.a.b.interceptor.AInterceptor - AInterceptor preHandle
[INFO ] [2025-12-03 23:03:11.792] [http-nio-9090-exec-2] [REQ-715ada0abaf74a959414802237aaa5c4] o.a.b.interceptor.AInterceptor - AInterceptor postHandle
[INFO ] [2025-12-03 23:03:11.792] [http-nio-9090-exec-2] [REQ-715ada0abaf74a959414802237aaa5c4] o.a.b.interceptor.BInterceptor - BInterceptor postHandle
[INFO ] [2025-12-03 23:03:11.792] [http-nio-9090-exec-2] [REQ-715ada0abaf74a959414802237aaa5c4] o.a.b.interceptor.CInterceptor - CInterceptor postHandle
[INFO ] [2025-12-03 23:03:11.792] [http-nio-9090-exec-2] [REQ-715ada0abaf74a959414802237aaa5c4] o.a.b.interceptor.AInterceptor - AInterceptor afterCompletion
[INFO ] [2025-12-03 23:03:11.792] [http-nio-9090-exec-2] [REQ-715ada0abaf74a959414802237aaa5c4] o.a.b.interceptor.BInterceptor - BInterceptor afterCompletion
[INFO ] [2025-12-03 23:03:11.792] [http-nio-9090-exec-2] [REQ-715ada0abaf74a959414802237aaa5c4] o.a.b.interceptor.CInterceptor - CInterceptor afterCompletion

其實這不難理解,我們可以類似將這三個攔截器當(dāng)作先進后出的棧結(jié)構(gòu)。preHandle作為Controller的Handler Method的前置邏輯,按照正向的順序執(zhí)行。postHandle和afterCompletion簡單理解成后置邏輯,按照反向的順序執(zhí)行。

四、過濾器 VS 攔截器

先說結(jié)論,過濾器和攔截器的作用范圍不一樣。前者是Java EE標(biāo)準(zhǔn)中Servlet規(guī)范提供的功能,它能處理任何進入Servlet容器的請求。比如靜態(tài)資源,http請求,都能通過過濾器攔截。攔截器是Spring MVC提供的功能,它的作用范圍屬于Spring容器,可以簡單理解成攔截器是對Controller層的攔截。如果用一個請求管道類比,過濾器能從管道最開始進行攔截,而攔截器只能到等待請求管道執(zhí)行到Spring中才能開始攔截。

最核心的差異是過濾器基于Servlet 容器、攔截器基于 Spring 容器;過濾器只能在請求前后操作,攔截器可深入到 Controller方法執(zhí)行環(huán)節(jié)

本文討論的過濾器和攔截器很類似ASP.NET Core中的中間件與過濾器,前者是作用于整個請求管道,后者是作用于Spring/ASP.NET Core框架,可以說是同種思想在不同框架中思想。如果有ASP.NET Core開發(fā)背景的小伙伴可以類比去理解

到此這篇關(guān)于Spring Boot Interceptor的原理、配置、順序控制及與Filter的關(guān)鍵區(qū)別的文章就介紹到這了,更多相關(guān)SpringBoot Interceptor內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java數(shù)據(jù)結(jié)構(gòu)二叉樹難點解析

    Java數(shù)據(jù)結(jié)構(gòu)二叉樹難點解析

    樹是一種重要的非線性數(shù)據(jù)結(jié)構(gòu),直觀地看,它是數(shù)據(jù)元素(在樹中稱為結(jié)點)按分支關(guān)系組織起來的結(jié)構(gòu),很象自然界中的樹那樣。樹結(jié)構(gòu)在客觀世界中廣泛存在,如人類社會的族譜和各種社會組織機構(gòu)都可用樹形象表示
    2021-10-10
  • Java多線程中Lock鎖的使用小結(jié)

    Java多線程中Lock鎖的使用小結(jié)

    這篇文章主要介紹了Java多線程中Lock鎖的使用小結(jié),本節(jié)主要講了它的基本使用,大家可以舉一反三,試試什么條件下會導(dǎo)致死鎖,需要的朋友可以參考下
    2022-06-06
  • Springboot集成SSE實現(xiàn)單工通信消息推送流程詳解

    Springboot集成SSE實現(xiàn)單工通信消息推送流程詳解

    SSE簡單的來說就是服務(wù)器主動向前端推送數(shù)據(jù)的一種技術(shù),它是單向的,也就是說前端是不能向服務(wù)器發(fā)送數(shù)據(jù)的。SSE適用于消息推送,監(jiān)控等只需要服務(wù)器推送數(shù)據(jù)的場景中,下面是使用Spring Boot來實現(xiàn)一個簡單的模擬向前端推動進度數(shù)據(jù),前端頁面接受后展示進度條
    2022-11-11
  • javaCV視頻處理之提取人像視頻

    javaCV視頻處理之提取人像視頻

    這篇文章主要介紹了利用JavaCV實現(xiàn)提取視頻中的人像并保存為視頻,文中的示例代碼講解詳細,對我們學(xué)習(xí)JavaCV有一定的幫助,需要的可以參考一下
    2021-12-12
  • Java中StringBuilder與StringBuffer的區(qū)別

    Java中StringBuilder與StringBuffer的區(qū)別

    在Java編程中,字符串的拼接是一項常見的操作。為了有效地處理字符串的拼接需求,Java提供了兩個主要的類:StringBuilder和StringBuffer,本文主要介紹了Java中StringBuilder與StringBuffer的區(qū)別,感興趣的可以了解一下
    2023-08-08
  • IDEA2022.2的簡介、下載與安裝、配置教程

    IDEA2022.2的簡介、下載與安裝、配置教程

    IDEA是JetBrains公司推出一個集成開發(fā)工具,是Java開發(fā)工具中的翹楚,基于這個開發(fā)工具可以快速開發(fā)我們的Java相關(guān)項目,本文重點給大家介紹IDEA2022.2的簡介、下載與安裝、初步配置,感興趣的朋友一起看看吧
    2022-11-11
  • Springboot整合minio實現(xiàn)文件服務(wù)的教程詳解

    Springboot整合minio實現(xiàn)文件服務(wù)的教程詳解

    這篇文章主要介紹了Springboot整合minio實現(xiàn)文件服務(wù)的教程,文中的示例代碼講解詳細,對我們的工作或?qū)W習(xí)有一定幫助,需要的可以參考一下
    2022-06-06
  • AsyncHttpClient的TimeoutTimerTask連接池異步超時

    AsyncHttpClient的TimeoutTimerTask連接池異步超時

    這篇文章主要為大家介紹了AsyncHttpClient的TimeoutTimerTask連接池異步超時源碼流程解讀,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-12-12
  • JAVA保證HashMap線程安全的幾種方式

    JAVA保證HashMap線程安全的幾種方式

    HashMap是線程不安全的,這意味著如果多個線程并發(fā)地訪問和修改同一個HashMap實例,可能會導(dǎo)致數(shù)據(jù)不一致和其他線程安全問題,本文主要介紹了JAVA保證HashMap線程安全的幾種方式,具有一定的參考價值,感興趣的可以了解一下
    2025-04-04
  • SpringBoot如何使用mica-xss防止Xss攻擊

    SpringBoot如何使用mica-xss防止Xss攻擊

    這篇文章主要介紹了SpringBoot如何使用mica-xss防止Xss攻擊問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-01-01

最新評論

兴山县| 天门市| 邯郸县| 中江县| 柳州市| 志丹县| 札达县| 安溪县| 城步| 景德镇市| 静海县| 濮阳市| 湖南省| 甘德县| 昌邑市| 柳河县| 广西| 沛县| 公安县| 响水县| 广州市| 镶黄旗| 长阳| 江北区| 安多县| 清流县| 道真| 昌平区| 安康市| 黎川县| 视频| 崇仁县| 青神县| 迁安市| 专栏| 广宁县| 遂平县| 义马市| 韶山市| 高邮市| 微山县|