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

Spring Mvc中攔截器Interceptor用法解讀

 更新時(shí)間:2025年03月25日 10:03:39   作者:透明果凍  
這篇文章主要介紹了Spring Mvc中攔截器Interceptor用法,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教

一、概述

攔截器常用于在請求處理的不同階段插入自定義邏輯。

Spring MVC的攔截器作用是在請求到達(dá)控制器之前或之后進(jìn)行攔截,可以對請求和響應(yīng)進(jìn)行一些特定的處理。

如:

  • 登錄驗(yàn)證:對于需要登錄才能訪問的網(wǎng)址,使用攔截器可以判斷用戶是否已登錄,如果未登錄則跳轉(zhuǎn)到登錄頁面。
  • 權(quán)限校驗(yàn):根據(jù)用戶權(quán)限對部分網(wǎng)址進(jìn)行訪問控制,拒絕未經(jīng)授權(quán)的用戶訪問。
  • 請求日志:記錄請求信息,例如請求地址、請求參數(shù)、請求時(shí)間等,用于排查問題和性能優(yōu)化。
  • 更改響應(yīng):可以對響應(yīng)的內(nèi)容進(jìn)行修改,例如添加頭信息、調(diào)整響應(yīng)內(nèi)容格式等。

二、攔截器和過濾器之間的區(qū)別

關(guān)于過濾器可以看我之前的文章過濾器Filter的介紹和使用。

我們很容易發(fā)現(xiàn)攔截器和過濾器十分相似,他們都是對某一階段的前后進(jìn)行攔截,進(jìn)行一些處理。那么他們之間有什么不同呢?

過濾器(Filter)是servlet中定義的,而攔截器(HandlerInterceptor)則是由Spring MVC框架提供

二者所作用的范圍不同

  • 過濾器更注重在**請求和響應(yīng)(即在Servlet之前)**的流程中進(jìn)行處理,可以修改請求和響應(yīng)的內(nèi)容,例如設(shè)置編碼和字符集、請求頭、狀態(tài)碼等。
  • 攔截器則更加側(cè)重于對控制器進(jìn)行前置或后置處理,在請求到達(dá)控制器之前或之后進(jìn)行特定的操作,例如打印日志、權(quán)限驗(yàn)證等。

三、自定義實(shí)現(xiàn)攔截器

Spring MVC 提供了 HandlerInterceptor 接口,開發(fā)者可以通過實(shí)現(xiàn)這個(gè)接口來創(chuàng)建自定義的攔截器。

其中定義了三個(gè)默認(rèn)方法,用于對不同階段進(jìn)行攔截:

preHandle(HttpServletRequest request, HttpServletResponse response, Object handler):
  • 在控制器方法執(zhí)行前調(diào)用。
  • 返回 true 表示繼續(xù)執(zhí)行后續(xù)的攔截器和控制器方法;返回 false 表示中斷執(zhí)行,不再調(diào)用后續(xù)的攔截器和控制器方法。
  • 可以用于權(quán)限驗(yàn)證、日志記錄等。
postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView):
  • 在控制器方法執(zhí)行后,但在視圖渲染前調(diào)用。
  • 可以用于修改 ModelAndView 對象,添加額外的數(shù)據(jù)等。
afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex):
  • 在整個(gè)請求處理完成后調(diào)用,無論是否發(fā)生異常。
  • 可以用于資源清理、日志記錄等。

創(chuàng)建自定義攔截器:

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class MyInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 在控制器方法執(zhí)行前調(diào)用
        System.out.println("preHandle..." );
        //這里我們直接返回true
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        // 在控制器方法執(zhí)行后,但在視圖渲染前調(diào)用
        System.out.println("postHandle...");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        // 在整個(gè)請求處理完成后調(diào)用
        System.out.println("AfterCompletion");
    }
}

此時(shí)要想要該攔截器生效,我們還需在spring mvc配置文件中進(jìn)行配置(默認(rèn)對所有控制器進(jìn)行攔截)

<mvc:interceptors>
    <mvc:interceptor>
        <!--設(shè)置要攔截的路徑-->
        <mvc:mapping path="/**"/>
        <!--指定不進(jìn)行攔截的路徑-->
        <mvc:exclude-mapping path="/test"/>
        <!--配置自定義攔截器的類路徑-->
        <bean class="com.example.MyInterceptor"/>
    </mvc:interceptor>
</mvc:interceptors>

也可以通過在自定義 攔截器的類上加上@component注解,此時(shí)的配置文件為

<mvc:interceptors>
    <mvc:interceptor>
        <!--設(shè)置要攔截的路徑-->
        <mvc:mapping path="/**"/>
        <!--指定不進(jìn)行攔截的路徑-->
        <mvc:exclude-mapping path="/test"/>
        <!--默認(rèn)名字為類名首字母小寫-->
        <ref bean="myInterceptor"></ref>
    </mvc:interceptor>
</mvc:interceptors>

四、多個(gè)攔截器的執(zhí)行順序

在 Spring MVC 中,多個(gè)攔截器可以組成一個(gè)攔截器鏈,按照注冊(配置)順序依次執(zhí)行。

假設(shè)現(xiàn)在按順序注冊三個(gè)攔截器Interceptor1,Interceptor2,Interceptor3。

當(dāng)所有的攔截器的preHandle方法都返回true時(shí):

  • preHandle執(zhí)行順序:Interceptor1->Interceptor2->Interceptor3 (順序執(zhí)行)
  • postHandle執(zhí)行順序:Interceptor3->Interceptor2->Interceptor1 (逆序執(zhí)行)
  • afterCompletion執(zhí)行順序:Interceptor3->Interceptor2->Interceptor1 (逆序執(zhí)行)

當(dāng)某一個(gè)攔截器的preHandle方法返回false時(shí),這里假設(shè)為Interceptor3

  • preHandle執(zhí)行順序:Interceptor1->Interceptor2->Interceptor3 (順序執(zhí)行直到某一個(gè)攔截器返回false)
  • postHandle不執(zhí)行,控制器方法也不執(zhí)行
  • afterCompletion執(zhí)行順序:Interceptor2->Interceptor1 (返回false的攔截器之前的攔截器逆序執(zhí)行)

為什么是這樣的順序呢?我們觀察源碼可以發(fā)現(xiàn):

  • preHandle源碼分析
boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {
   		 //interceptorList是一個(gè)ArrayList集合,按順序存放了所有的攔截器	
    	//下標(biāo)從0開始,從這里我們可以知道為什么是順序執(zhí)行的。
  		//this.interceptorIndex = i++,注意這個(gè)代碼,如果返回false,則它的值則表示當(dāng)前返回false的攔截器的下標(biāo)
        for(int i = 0; i < this.interceptorList.size(); this.interceptorIndex = i++) {
            HandlerInterceptor interceptor = (HandlerInterceptor)this.interceptorList.get(i);
            //如果返回false
            if (!interceptor.preHandle(request, response, this.handler)) {
                //執(zhí)行AfterCompletion,這里我們就知道為什么不執(zhí)行postHandle,而執(zhí)行AfterCompletion了
                this.triggerAfterCompletion(request, response, (Exception)null);
                return false;
            }
        }

        return true;
    }
  • postHandle源碼分析
void applyPostHandle(HttpServletRequest request, HttpServletResponse response, @Nullable ModelAndView mv) throws Exception {
    	//可以看到這里是從最后一個(gè)攔截器開始逆序遍歷
        for(int i = this.interceptorList.size() - 1; i >= 0; --i) {
            HandlerInterceptor interceptor = (HandlerInterceptor)this.interceptorList.get(i);
            interceptor.postHandle(request, response, this.handler, mv);
        }

    }
  • afterCompletion源碼分析
void applyPostHandle(HttpServletRequest request, HttpServletResponse response, @Nullable ModelAndView mv) throws Exception {
    	//this.interceptorList.size() - 1表示當(dāng)前返回false的攔截器的上一個(gè)的下標(biāo)
    	//注意這里是--i
    	//這也就解釋了為什么是返回false的攔截器之前的攔截器逆序執(zhí)行
        for(int i = this.interceptorList.size() - 1; i >= 0; --i) {
            HandlerInterceptor interceptor = (HandlerInterceptor)this.interceptorList.get(i);
            interceptor.postHandle(request, response, this.handler, mv);
        }

    }

總結(jié)

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • SpringBoot+SpringSecurity實(shí)現(xiàn)認(rèn)證的流程詳解

    SpringBoot+SpringSecurity實(shí)現(xiàn)認(rèn)證的流程詳解

    這篇文章主要介紹了SpringBoot+SpringSecurity實(shí)現(xiàn)認(rèn)證的流程,文中通過代碼示例和圖文結(jié)合的方式講解的非常詳細(xì),對大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下
    2024-05-05
  • Spring中@PathVariable和@RequestParam注解的用法區(qū)別

    Spring中@PathVariable和@RequestParam注解的用法區(qū)別

    這篇文章主要介紹了Spring中@PathVariable和@RequestParam注解的用法區(qū)別,@PathVariable 是 Spring 框架中的一個(gè)注解,用于將 URL 中的變量綁定到方法的參數(shù)上,它通常用于處理 RESTful 風(fēng)格的請求,從 URL 中提取參數(shù)值,并將其傳遞給方法進(jìn)行處理,需要的朋友可以參考下
    2024-01-01
  • java二維碼生成的方法

    java二維碼生成的方法

    這篇文章主要為大家詳細(xì)介紹了java二維碼生成的方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-06-06
  • Java 8中HashMap的底層原理解析

    Java 8中HashMap的底層原理解析

    HashMap作為Java中常用的數(shù)據(jù)結(jié)構(gòu)之一,在JDK 1.8中經(jīng)過了一系列的優(yōu)化和改進(jìn),深入理解其底層原理,包括哈希算法、數(shù)組與鏈表結(jié)構(gòu)、紅黑樹的引入等,有助于更好地使用和理解HashMap的性能特性,這篇文章主要介紹了Java 8中HashMap的底層原理,需要的朋友可以參考下
    2023-11-11
  • java虛擬機(jī)中多線程總結(jié)

    java虛擬機(jī)中多線程總結(jié)

    在本篇內(nèi)容中小編給大家分享的是關(guān)于java虛擬機(jī)中多線程的知識點(diǎn)總結(jié)內(nèi)容,需要的朋友們參考學(xué)習(xí)下。
    2019-06-06
  • java操作gaussDB數(shù)據(jù)庫的實(shí)現(xiàn)示例

    java操作gaussDB數(shù)據(jù)庫的實(shí)現(xiàn)示例

    本文主要介紹了java操作gaussDB數(shù)據(jù)庫的實(shí)現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-07-07
  • SpringCloud FeignClient 超時(shí)設(shè)置

    SpringCloud FeignClient 超時(shí)設(shè)置

    FeignClient?默認(rèn)的超時(shí)時(shí)間可能不滿足你的需求,你可以通過幾種方式來自定義這些超時(shí)設(shè)置,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-08-08
  • springboot-jpa的實(shí)現(xiàn)操作

    springboot-jpa的實(shí)現(xiàn)操作

    這篇文章主要介紹了springboot-jpa的實(shí)現(xiàn)操作,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-03-03
  • Spring?控制反轉(zhuǎn)和依賴注入的具體使用

    Spring?控制反轉(zhuǎn)和依賴注入的具體使用

    本文主要介紹了Spring?控制反轉(zhuǎn)和依賴注入,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-02-02
  • Java?并發(fā)編程之ForkJoin框架

    Java?并發(fā)編程之ForkJoin框架

    這篇文章主要為大家介紹了Java?ForkJoin框架,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助,希望能夠給你帶來幫助
    2021-11-11

最新評論

泸定县| 呈贡县| 视频| 新郑市| 抚远县| 隆德县| 东明县| 临桂县| 余庆县| 赞皇县| 库伦旗| 响水县| 淅川县| 郯城县| 平顶山市| 顺昌县| 涪陵区| 贵阳市| 高台县| 松江区| 中阳县| 疏勒县| 霍州市| 白水县| 汝城县| 富裕县| 个旧市| 沅陵县| 承德市| 枝江市| 藁城市| 临沭县| 保亭| 金堂县| 塔河县| 宁南县| 宿迁市| 梧州市| 海原县| 铁岭市| 资中县|