spring 攔截器/過濾器

攔截器

要了解Spring攔截器的作用尘惧,我們需要先解釋一下HTTP請求的執(zhí)行鏈惭适。DispatcherServlet捕獲每個請求笙瑟。調(diào)度員做的第一件事就是將接收到的URL和相應(yīng)的controller進行映射(controller必須恰到好處地處理當(dāng)前的請求)。但是癞志,在到達對應(yīng)的controller之前往枷,請求可以被攔截器處理。這些攔截器就像過濾器凄杯。只有當(dāng)URL找到對應(yīng)于它們的映射時才調(diào)用它們错洁。在通過攔截器(攔截器預(yù)處理,其實也可以說前置處理)進行前置處理后戒突,請求最終到達controller屯碴。之后,發(fā)送請求生成視圖膊存。但是在這之前导而,攔截器還是有可能來再次處理它(攔截器后置處理)忱叭。只有在最后一次操作之后,視圖解析器才能捕獲數(shù)據(jù)并輸出視圖今艺。

在Spring Boot中韵丑,攔截器分為兩類:

一種是對請求進來的url進行攔截,HandlerInterceptor接口虚缎;
一種是對發(fā)送出去的請求進行攔截撵彻,ClientHttpRequestInterceptor。

處理程序映射攔截器基于org.springframework.web.servlet.HandlerInterceptor接口遥巴。和之前簡要描述的那樣千康,它們可以在將其發(fā)送到控制器(方法前使用preHandle)之前或之后(方法后使用postHandle)攔截請求享幽。preHandle方法返回一個布爾值铲掐,如果返回false,則可以在執(zhí)行鏈中執(zhí)行中斷請求處理值桩。此接口中還有一個方法afterCompletion摆霉,只有在preHandler方法發(fā)送為true時才會在渲染視圖后調(diào)用它(完成請求處理后的回調(diào),即渲染視圖后)奔坟。

攔截器也可以在新線程中啟動携栋。在這種情況下,攔截器必須實現(xiàn)org.springframework.web.servlet.AsyncHandlerInterceptor接口咳秉。它繼承HandlerInterceptor并提供一個方法afterConcurrentHandlingStarted婉支。每次處理程序得到正確執(zhí)行時,都會調(diào)用此方法而不是調(diào)用postHandler()和afterCompletion()澜建。它也可以對發(fā)送請求進行異步處理向挖。通過Spring源碼此方法注釋可以知道,這個方法的典型的應(yīng)用是可以用來清理本地線程變量炕舵。

public class LotteryInterceptor implements HandlerInterceptor {

    public static final String ATTR_NAME = "lottery_winner";
    private static final Logger LOGGER = LoggerFactory.getLogger(LotteryInterceptor.class);

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception exception) throws Exception {
        LOGGER.debug("[LotteryInterceptor] afterCompletion");

    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView view) throws Exception {
        LOGGER.debug("[LotteryInterceptor] postHandle");

    }

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        LOGGER.debug("[LotteryInterceptor] preHandle");
        if (request.getSession().getAttribute(ATTR_NAME) == null) {
            Random random = new Random();
            int i = random.nextInt(10);
            request.getSession().setAttribute(ATTR_NAME, i%2 == 0);
        }
        return true;
    }

}

關(guān)于相應(yīng)controller中要展示的信息:

@Controller
public class TestController {
        private static final Logger LOGGER = LoggerFactory.getLogger(TestController.class);
    @RequestMapping(value = "/test", method = RequestMethod.GET)
    public String test(HttpServletRequest request) {
        LOGGER.debug("Controller asks, are you a lottery winner ? "+request.getSession().getAttribute(LotteryInterceptor.ATTR_NAME));
        return "test";
    }
}

結(jié)果:

[LotteryInterceptor] preHandle
Controller asks, are you a lottery winner ? false
[LotteryInterceptor] postHandle
[LotteryInterceptor] afterCompletion

HandlerInterceptor和ClientHttpRequestInterceptor的區(qū)別

HandlerInterceptor 和 ClientHttpRequestInterceptor 都是 Spring 框架中的攔截器何之,但它們的作用和使用場景不同。下面是它們之間的主要區(qū)別:

作用范圍:

HandlerInterceptor 主要用于攔截處理 Spring 應(yīng)用中接收到的 HTTP 請求咽筋。它允許你在請求處理之前溶推、處理之后、以及視圖渲染完成后執(zhí)行自定義邏輯奸攻。

ClientHttpRequestInterceptor 主要用于攔截和處理 Spring 應(yīng)用中使用 RestTemplate 或 WebClient 發(fā)送的 HTTP 請求蒜危。它讓你在請求發(fā)送之前,對請求頭睹耐、請求體等進行自定義處理辐赞。

使用場景:

HandlerInterceptor 通常用于身份驗證、授權(quán)疏橄、日志記錄占拍、跨域資源共享(CORS)等應(yīng)用內(nèi)請求處理相關(guān)的功能略就。

ClientHttpRequestInterceptor 通常用于處理服務(wù)間通信,例如在請求頭中添加認證信息晃酒、自定義請求頭表牢、請求數(shù)據(jù)處理、重試策略等贝次。

過濾器

在 Spring Boot 中崔兴,過濾器(Filter)是用于在 Servlet 容器級別攔截和處理 HTTP 請求的組件。它們通常用于實現(xiàn)諸如身份驗證蛔翅、授權(quán)敲茄、日志記錄、請求和響應(yīng)的數(shù)據(jù)轉(zhuǎn)換等功能山析。過濾器位于整個請求處理鏈的最前端堰燎,因此在請求到達 Spring 應(yīng)用的任何其他組件之前,都會先經(jīng)過過濾器處理笋轨。

過濾器和攔截器各自優(yōu)勢與區(qū)別秆剪?

image.png

過濾器(Filter)和攔截器(Interceptor)在某些方面的功能確實相似,但它們在使用場景爵政、處理層級和實現(xiàn)方式上有所不同仅讽。以下是過濾器和攔截器之間的主要區(qū)別和各自的優(yōu)勢:

處理層級:

過濾器(Filter)基于 Java Servlet 規(guī)范,在 Servlet 容器級別處理請求钾挟。過濾器在整個請求處理鏈的最前端洁灵,因此在請求到達 Spring 應(yīng)用的任何其他組件之前,都會先經(jīng)過過濾器處理掺出。

攔截器(Interceptor)是 Spring MVC 的一部分徽千,用于處理 Spring 應(yīng)用中接收到的請求。攔截器在 Spring 處理請求的過程中起作用蛛砰,位于過濾器之后罐栈。

使用場景:

過濾器(Filter)通常用于實現(xiàn)通用的、與框架無關(guān)的功能泥畅,如身份驗證荠诬、授權(quán)、日志記錄位仁、請求和響應(yīng)的數(shù)據(jù)轉(zhuǎn)換等柑贞。

攔截器(Interceptor)通常用于實現(xiàn)與 Spring 框架相關(guān)的功能,如驗證用戶身份聂抢、授權(quán)钧嘶、請求參數(shù)處理、異常處理等琳疏。

優(yōu)勢:

過濾器(Filter)可以處理任何 Web 應(yīng)用的請求有决,不局限于 Spring闸拿。過濾器允許你在請求到達任何框架組件之前對其進行處理,提供了更大的控制范圍书幕。

攔截器(Interceptor)更緊密地集成在 Spring MVC 中新荤,因此可以更方便地使用 Spring 提供的功能。攔截器可以訪問 Spring 上下文台汇,讓你能夠輕松地使用其他 Spring 組件和服務(wù)苛骨。

實現(xiàn)方式:

過濾器(Filter)需要實現(xiàn) javax.servlet.Filter 接口,并實現(xiàn) init苟呐、doFilter 和 destroy 方法痒芝。

攔截器(Interceptor)需要實現(xiàn) HandlerInterceptor 接口(對于請求攔截)或 ClientHttpRequestInterceptor 接口(對于客戶端請求攔截),并實現(xiàn)相應(yīng)的方法牵素。

總的來說严衬,過濾器和攔截器在功能上有一定的重疊,但它們的使用場景两波、處理層級和實現(xiàn)方式有所不同瞳步。選擇使用過濾器還是攔截器取決于你的具體需求和場景闷哆。當(dāng)你需要處理與框架無關(guān)的請求時腰奋,可以使用過濾器;當(dāng)你需要實現(xiàn)與 Spring 框架相關(guān)的功能時抱怔,攔截器可能是更好的選擇劣坊。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市屈留,隨后出現(xiàn)的幾起案子局冰,更是在濱河造成了極大的恐慌,老刑警劉巖灌危,帶你破解...
    沈念sama閱讀 217,406評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件康二,死亡現(xiàn)場離奇詭異,居然都是意外死亡勇蝙,警方通過查閱死者的電腦和手機沫勿,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,732評論 3 393
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來味混,“玉大人产雹,你說我怎么就攤上這事∥涛” “怎么了蔓挖?”我有些...
    開封第一講書人閱讀 163,711評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長馆衔。 經(jīng)常有香客問我瘟判,道長怨绣,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,380評論 1 293
  • 正文 為了忘掉前任拷获,我火速辦了婚禮梨熙,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘刀诬。我一直安慰自己咽扇,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,432評論 6 392
  • 文/花漫 我一把揭開白布陕壹。 她就那樣靜靜地躺著质欲,像睡著了一般。 火紅的嫁衣襯著肌膚如雪糠馆。 梳的紋絲不亂的頭發(fā)上嘶伟,一...
    開封第一講書人閱讀 51,301評論 1 301
  • 那天,我揣著相機與錄音又碌,去河邊找鬼九昧。 笑死,一個胖子當(dāng)著我的面吹牛毕匀,可吹牛的內(nèi)容都是我干的铸鹰。 我是一名探鬼主播,決...
    沈念sama閱讀 40,145評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼皂岔,長吁一口氣:“原來是場噩夢啊……” “哼蹋笼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起躁垛,我...
    開封第一講書人閱讀 39,008評論 0 276
  • 序言:老撾萬榮一對情侶失蹤剖毯,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后教馆,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體逊谋,經(jīng)...
    沈念sama閱讀 45,443評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,649評論 3 334
  • 正文 我和宋清朗相戀三年土铺,在試婚紗的時候發(fā)現(xiàn)自己被綠了胶滋。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,795評論 1 347
  • 序言:一個原本活蹦亂跳的男人離奇死亡舒憾,死狀恐怖镀钓,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情镀迂,我是刑警寧澤丁溅,帶...
    沈念sama閱讀 35,501評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站探遵,受9級特大地震影響窟赏,放射性物質(zhì)發(fā)生泄漏妓柜。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,119評論 3 328
  • 文/蒙蒙 一涯穷、第九天 我趴在偏房一處隱蔽的房頂上張望棍掐。 院中可真熱鬧,春花似錦拷况、人聲如沸作煌。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,731評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽粟誓。三九已至,卻和暖如春起意,著一層夾襖步出監(jiān)牢的瞬間鹰服,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,865評論 1 269
  • 我被黑心中介騙來泰國打工揽咕, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留悲酷,地道東北人。 一個月前我還...
    沈念sama閱讀 47,899評論 2 370
  • 正文 我出身青樓亲善,卻偏偏與公主長得像设易,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子逗爹,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,724評論 2 354

推薦閱讀更多精彩內(nèi)容