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

SpringBoot 攔截器 (Interceptor)與切面 (AOP)示例、作用及適用場景分析

 更新時間:2026年01月30日 11:19:24   作者:康小莊  
攔截器是SpringMVC框架的組件,基于Java動態(tài)代理實現(xiàn),作用于Web層(Controller 層),僅能攔截HTTP請求的處理過程,生命周期與 SpringMVC的請求處理流程綁定,本文介紹SpringBoot攔截器 (Interceptor)與切面(AOP)示例、作用及適用場景分析,感興趣的朋友一起看看吧

SpringBoot 攔截器 (Interceptor) 與切面 (AOP):示例、作用、及適用場景

一、攔截器 (Interceptor):SpringMVC 層的請求攔截器

攔截器是SpringMVC 框架的組件,基于Java 動態(tài)代理實現(xiàn),作用于Web 層(Controller 層),僅能攔截 HTTP 請求的處理過程,生命周期與 SpringMVC 的請求處理流程綁定。

核心作用

  1. 攔截 Controller 層的 HTTP 請求(如 GET/POST 請求);
  2. 實現(xiàn)請求前的預(yù)處理(如登錄校驗、token 驗證、跨域配置);
  3. 實現(xiàn)請求后的后置處理(如響應(yīng)數(shù)據(jù)統(tǒng)一封裝);
  4. 實現(xiàn)請求完成后的最終處理(如資源釋放、請求日志記錄)。

1.自定義攔截器:實現(xiàn)HandlerInterceptor接口

@Component
@Slf4j
public class CompanyContextInterceptor implements HandlerInterceptor {
    @Resource
    private RedisTemplate<String, Object> redisTemplate;
    private static final String REDIS_TOKEN_KEY_PREFIX = "login:";
    // 請求開始前:解析 Header,設(shè)置公司編碼到上下文
    @Override
    public boolean preHandle(HttpServletRequest request, @NotNull HttpServletResponse response, @NotNull Object handler) throws Exception {
        // 1. 從請求頭獲取Token(Bearer Token格式)
        String authHeader = request.getHeader("Authorization");
        if (StringUtils.isBlank(authHeader) || !authHeader.startsWith("Bearer ")) {
            // 未攜帶Token,直接通過(或返回401,根據(jù)業(yè)務(wù)需求)
            return true;
        }
        String token = authHeader.substring(7); // 截取Bearer后的Token
        // 2. 從Redis查詢登錄用戶信息
        String redisKey = REDIS_TOKEN_KEY_PREFIX + token;
        LoginController.LoginWxUser loginWxUser = (LoginController.LoginWxUser) redisTemplate.opsForValue().get(redisKey);
        if (loginWxUser == null || StringUtils.isBlank(loginWxUser.getPhone())) {
            // Token無效/過期,直接通過(或返回401)
            return true;
        }
        // 3. 核心:將loginWxUser存入request,key必須是「loginWxUser」(和接口一致?。?
        request.setAttribute("loginWxUser", loginWxUser);
        // 可選:Token續(xù)期
        redisTemplate.expire(redisKey, 7, TimeUnit.DAYS);
        // 獲取請求路徑
        String requestURI = request.getRequestURI();
        // 檢查是否為需要忽略的登錄接口
        if (requestURI.equals("/workaffairs/api/user/loginByPhone") ||
                requestURI.startsWith("/workaffairs/api/user/loginByPhone")) {
            return true; // 直接放行,不設(shè)置公司編碼
        }
        // 從 Header 獲取公司編碼
        String companyCode = request.getHeader("x-Company-Code");
        if (companyCode != null && !companyCode.isEmpty()) {
            CompanyContextHolder.setCompanyCode(companyCode);
            log.info("獲取到公司編碼----" + companyCode);
        }
        return true; // 放行請求
    }
    // 請求結(jié)束后:清理上下文(必須執(zhí)行,避免內(nèi)存泄漏)
    @Override
    public void afterCompletion(@NotNull HttpServletRequest request, @NotNull HttpServletResponse response, @NotNull Object handler, Exception ex) throws Exception {
        CompanyContextHolder.clear();
    }
}

2.攔截器配置類:實現(xiàn)WebMvcConfigurer接口

/**
 * 攔截器配置類:注冊攔截器并配置攔截規(guī)則
 */
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
    // 注入自定義攔截器
    @Resource
    private CompanyContextInterceptor companyContextInterceptor;
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(companyContextInterceptor)
                // 攔截所有需要切換數(shù)據(jù)源的業(yè)務(wù)接口(根據(jù)你的實際路徑調(diào)整)
                .addPathPatterns("/purchase/**", "/delivery/**","/api/user/getSupplierByCompany")
                // 排除不需要攔截的接口(比如登錄接口)
                .excludePathPatterns("/api/user/loginByPhone");
    }
}

二、切面 (AOP):面向切面的通用橫切邏輯實現(xiàn)

核心概念

切面是Spring AOP 框架的核心,基于JDK 動態(tài)代理(針對接口)+CGLIB 動態(tài)代理(針對類) 實現(xiàn),是面向切面編程的落地方式,可作用于Spring 容器管理的所有 Bean(Controller、Service、Dao、普通組件等),無層級限制。

核心作用

  1. 提取通用橫切邏輯(與業(yè)務(wù)無關(guān)、可復(fù)用的邏輯),如日志記錄、事務(wù)管理、耗時統(tǒng)計、異常統(tǒng)一捕獲;
  2. 實現(xiàn)業(yè)務(wù)代碼與橫切邏輯的解耦,無需在業(yè)務(wù)方法中硬編碼通用邏輯;
  3. 可對任意方法進行增強(前置增強、后置增強、環(huán)繞增強、異常增強等),支持靈活的切點表達式配置。

1.自定義切面

@Aspect // 聲明為切面類
@Component // 交給Spring容器管理
@Slf4j
public class DbOperationLogAspect {
    /**
     * 定義切點:指定切面作用的目標方法
     * 表達式規(guī)則:execution(訪問修飾符 返回值 包名.類名.方法名(參數(shù)類型))
     * 示例:匹配com.tgerp.workaffairs.mapper包下所有類的所有方法
     */
    @Pointcut("execution(* com.tgerp.workaffairs.mapper..*(..))")
    public void dbOperationPointCut() {
    }
    @Around("dbOperationPointCut()")
    public Object aroundDbOperation(ProceedingJoinPoint joinPoint) throws Throwable {
        // 1. 此時controller已經(jīng)執(zhí)行了setDbName,能拿到正確的數(shù)據(jù)庫名
        String currentDbName = DynamicDataSourceContextHolder.peek(); // 從數(shù)據(jù)源上下文拿
//        }
        String className = joinPoint.getTarget().getClass().getName();
        String methodName = joinPoint.getSignature().getName();
        // 打印日志
        log.info("[workaffairs-數(shù)據(jù)庫: {}] 執(zhí)行數(shù)據(jù)庫操作 - 類:{},方法:{}", currentDbName, className, methodName);
        try {
            return joinPoint.proceed();
        } catch (Exception e) {
            log.error("[workaffairs-數(shù)據(jù)庫: {}] 數(shù)據(jù)庫操作失敗 - 類:{},方法:{},異常信息:{}",
                    currentDbName, className, methodName, e.getMessage(), e);
            throw e;
        }
    }
}

三、攔截器與切面的適用場景

選型核心原則:根據(jù)橫切邏輯的「作用范圍」和「是否與 Web 請求相關(guān)」判斷

攔截器 (Interceptor):僅適用于Web 相關(guān)的橫切邏輯

所有與 HTTP 請求強綁定的場景,優(yōu)先使用攔截器,因為可直接獲取 Web 上下文(Request/Response),無需額外處理:

  1. 登錄 / 權(quán)限校驗:基于請求頭 / 參數(shù)驗證 token、會話、用戶身份;
  2. 跨域配置:統(tǒng)一設(shè)置響應(yīng)頭(Access-Control-Allow-Origin 等);
  3. 請求參數(shù)預(yù)處理:統(tǒng)一解析請求頭、請求參數(shù),如防 XSS 處理;
  4. 響應(yīng)數(shù)據(jù)統(tǒng)一封裝:對 Controller 返回的結(jié)果統(tǒng)一添加 code/msg/data 格式;
  5. Web 層日志記錄:記錄請求 URI、請求方式、IP、響應(yīng)狀態(tài)等 Web 相關(guān)信息;
  6. 接口限流:基于 IP / 請求頻率限制 HTTP 請求(如每秒最大請求數(shù))。

切面 (AOP):適用于通用、跨層的橫切邏輯

所有與業(yè)務(wù)無關(guān)、需要在多層級復(fù)用的通用橫切邏輯,優(yōu)先使用切面,解耦效果最佳,無環(huán)境依賴:

  1. 全局日志記錄:記錄方法的入?yún)?、出參、?zhí)行耗時(適用于 Service/Dao 層);
  2. 事務(wù)管理:通過@Transactional(底層基于 AOP)實現(xiàn)方法級事務(wù)控制;
  3. 方法級權(quán)限校驗:基于自定義注解(如 @RequiresPermission)實現(xiàn)方法訪問控制;
  4. 異常統(tǒng)一捕獲:捕獲指定層的異常,統(tǒng)一封裝異常響應(yīng)(如 Service 層業(yè)務(wù)異常);
  5. 緩存控制:實現(xiàn)方法級緩存(如查詢方法結(jié)果緩存,避免重復(fù)查詢);
  6. 性能監(jiān)控:統(tǒng)計指定方法的執(zhí)行耗時、調(diào)用次數(shù),做系統(tǒng)性能分析;
  7. 非 Web 環(huán)境的橫切邏輯:如定時任務(wù)、后臺服務(wù)的方法增強(無 Web 上下文,攔截器無法使用)。

實際項目中,攔截器和切面并非互斥,而是協(xié)同工作,各自負責(zé)專屬領(lǐng)域的橫切邏輯,形成完整的橫切體系:

例如:一個接口的完整處理流程中:

  1. 攔截器:在請求進入 Controller 前,完成登錄校驗、token 驗證(Web 層專屬);
  2. 切面:在 Service 層方法執(zhí)行時,完成耗時統(tǒng)計、事務(wù)管理、異常捕獲(通用跨層);
  3. 攔截器:在請求完成后,完成響應(yīng)數(shù)據(jù)封裝、Web 日志記錄(Web 層專屬)。

這種協(xié)同模式既保證了 Web 相關(guān)邏輯的高效處理,又實現(xiàn)了通用邏輯的跨層復(fù)用,是 SpringBoot 項目的標準實踐。

到此這篇關(guān)于SpringBoot 攔截器 (Interceptor)與切面 (AOP)示例、作用及適用場景分析的文章就介紹到這了,更多相關(guān)SpringBoot 攔截器和切面內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java語法關(guān)于泛型與類型擦除的分析

    Java語法關(guān)于泛型與類型擦除的分析

    泛型沒有其看起來那么深不可測,它并不神秘與神奇,泛型是Java 中一個很小巧的概念,但同時也是一個很容易讓人迷惑的知識點,它讓人迷惑的地方在于它的許多表現(xiàn)有點違反直覺
    2021-09-09
  • Java向kettle8.0傳遞參數(shù)的方式總結(jié)

    Java向kettle8.0傳遞參數(shù)的方式總結(jié)

    介紹了如何在Kettle中傳遞參數(shù)到轉(zhuǎn)換和作業(yè)中,包括設(shè)置全局properties、使用TransMeta和JobMeta的parameterValue,以及通過EL表達式獲取參數(shù)值
    2025-01-01
  • 詳解Java線程池隊列中的延遲隊列DelayQueue

    詳解Java線程池隊列中的延遲隊列DelayQueue

    這篇文章主要為大家詳細介紹了Java線程池隊列中的延遲隊列DelayQueue的相關(guān)資料,文中的示例代碼講解詳細,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2022-12-12
  • 一文教你利用Stream?API批量Mock數(shù)據(jù)的方法

    一文教你利用Stream?API批量Mock數(shù)據(jù)的方法

    在日常開發(fā)的過程中我們經(jīng)常會遇到需要mock一些數(shù)據(jù)的場景,比如說?mock?一些接口的返回或者說?mock?一些測試消息用于隊列生產(chǎn)者發(fā)送消息。本文將教你如何通過?Stream?API?批量?Mock?數(shù)據(jù),需要的可以參考一下
    2022-09-09
  • SpringBoot實現(xiàn)數(shù)據(jù)轉(zhuǎn)換的四種對象映射方案

    SpringBoot實現(xiàn)數(shù)據(jù)轉(zhuǎn)換的四種對象映射方案

    在項目開發(fā)中,對象之間的相互轉(zhuǎn)換是一個高頻操作,尤其在分層架構(gòu)的系統(tǒng)中,數(shù)據(jù)在實體對象(Entity)、數(shù)據(jù)傳輸對象(DTO)、值對象(VO)之間的轉(zhuǎn)換尤為常見,選擇一個高效、可靠的對象映射方案對提高系統(tǒng)性能和開發(fā)效率至關(guān)重要,本文將介紹4種對象映射方案
    2025-06-06
  • 解決springboot遇到autowire注入為null的問題

    解決springboot遇到autowire注入為null的問題

    這篇文章主要介紹了解決springboot遇到autowire注入為null的問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-03-03
  • Java中ArrayList集合的常用方法大全

    Java中ArrayList集合的常用方法大全

    這篇文章主要給大家介紹了關(guān)于Java中ArrayList集合的常用方法,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-01-01
  • Java中如何實現(xiàn)不可變Map詳解

    Java中如何實現(xiàn)不可變Map詳解

    這篇文章主要給大家介紹了關(guān)于Java中如何實現(xiàn)不可變Map的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作工具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2018-12-12
  • SpringBoot讀取Resource目錄文件的五種常見方式

    SpringBoot讀取Resource目錄文件的五種常見方式

    在Spring Boot開發(fā)中,我們經(jīng)常需要讀取src/main/resources目錄下的文件,src/main/resources 目錄下通常存放配置文件、模板、靜態(tài)資源、SQL腳本等,本文給大家介紹了SpringBoot讀取Resource目錄文件的五種常見方式,需要的朋友可以參考下
    2025-07-07
  • Spring中自定義Schema如何解析生效詳解

    Spring中自定義Schema如何解析生效詳解

    Spring2.5在2.0的基于Schema的Bean配置的基礎(chǔ)之上,再增加了擴展XML配置的機制。通過該機制,我們可以編寫自己的Schema,并根據(jù)自定義的Schema用自定的標簽配置Bean,下面這篇文章主要介紹了關(guān)于Spring中自定義Schema如何解析生效的相關(guān)資料,需要的朋友可以參考下
    2018-07-07

最新評論

桃源县| 郧西县| 枣阳市| 理塘县| 响水县| 北流市| 崇左市| 沙坪坝区| 新和县| 永修县| 桑植县| 清水县| 遂溪县| 奎屯市| 卫辉市| 云霄县| 婺源县| 玉环县| 娱乐| 余江县| 如东县| 永康市| 隆德县| 乾安县| 唐河县| 荔浦县| 威远县| 儋州市| 盖州市| 开江县| 龙岩市| 横山县| 兴安县| 南开区| 星子县| 元阳县| 浏阳市| 宁陵县| 揭东县| 武鸣县| 湘潭县|