前言前端
MVC過濾器在以前Asp.Net的時候就已經普遍使用啦,不論是面試仍是工做,總有一個考點或是需求涉及到,能夠絕不疑問的說,這個技術點是很是重要的; 在以前參與的面試中,得知不少小夥伴只知道有一兩個過濾器,而對其執行順序瞭解的仍是很模糊,少部分小夥伴甚至尚未使用過。這裏就詳細來講說這塊的內容。面試
正文後端
來,直接上菜,而後再慢慢品;在Asp.NetCore 中,MVC有如下五種過濾器,根據執行順序的不一樣,用於不一樣場景:
設計模式
上圖中大概的流程以下:
緩存
用戶發起一個請求;
服務器請求通過Asp.NetCore應用程序的中間件管道;測試
管道走完以後進入MVC的第一個過濾器:受權過濾器;設計
受權經過以後進入資源過濾器的前置方法;
日誌將異常過濾器加入使用,後續有異常能夠進行捕獲,以前若是發生異常不能捕獲;
中間件進行數據模型綁定,好比參數經過數據模型綁定傳參;
進入Action過濾器前置方法;
執行Action方法具體邏輯;
進入Action過濾器後置方法;
進入Result過濾器前置方法;
渲染Result結果;
進入Result過濾器後置方法;
進入資源過濾器的後置方法;
進入中間件管道返回;
最後將響應結果展示給用戶;
接下來就好好說說每種過濾器的使用,老規矩,仍是WebApi項目↓↓↓
受權過濾器(Authorization Filter)
受權,用於驗證請求是否有權限訪問對應的Action,通常包含登陸驗證、菜單權限(即接口權限)驗證等。受權過濾器只對請求進行驗證,是單向的,響應返回時不走該過濾器;
代碼擼起來:
這裏先進行全局註冊過濾器進行測試,即只要註冊以後,全部請求都須要通過受權過濾器校驗,後續單獨說說註冊方式範圍:
在默認生成的接口中打印字符串,方便看執行結果:
運行看結果:
經過上圖能夠看到,已經進入受權過濾器中進行相關邏輯判斷;若是將受權邏輯中的局部變量validate設置爲true,運行結果以下:
看過上一篇(跟我一塊兒學.NetCore之熟悉的接口權限驗證不能少(Jwt))的小夥伴確定有疑問:這和受權中間件中使用Authorize特性受權有什麼區別?沒看過的小夥伴也不要緊,應該也會有一樣的疑問;來,聽我慢慢道來,老套路,扒扒受權中間件的代碼,看看怎麼回事?
先來看看Authorize特性裏面都有什麼,關鍵是實現了IAuthorizeData接口,以下圖:
找到受權的入口點,即中間件註冊受權那裏着手,以下圖:
從而找AuthorizationMiddleware的具體實現,關鍵代碼以下圖:
總的來講,使用受權中間的時,標註Authorize特性的Action,會經過默認的AuthorizeFilter進行驗證處理,這就是爲何在上一節權限驗證的時候咱們沒有單獨編寫受權過濾器,而是偏重於校驗的邏輯,只關注驗證的角色或策略;這裏就不打算再看AuthorizeFilter的源碼,有興趣的小夥伴好好研究研究。
資源過濾器(Resource Filter)
資源過濾器分爲前置方法和後置方法,通常都會在前置方法作相關處理,好比說須要改改模型綁定的邏輯,但更多經常使用的是用於數據緩存處理,由於是在受權過濾器以後的第一個,若是取得緩存數據,直接返回結果,就減小後面代碼邏輯執行;後置方法在以後全部代碼邏輯執行完成,返回時通過。
代碼擼起來:
這裏仍是以全局的方式進行註冊資源過濾器:
運行效果以下:
將受權過濾器中的validate改成false,這裏模擬表明有權限繼續執行:
異常過濾器(Exception Filter)
用於服務器向客戶端寫入響應內容以前進行系統異常捕獲,通常用於業務場景統一異常的處理,若是沒有特殊需求,沒必要每種業務都進行異常處理,經過異常過濾器統一捕獲處理便可,記錄相關日誌,便於異常問題分析;
先模擬處理業務時,拋異常了,以下:
異常信息直接返回給用戶,體驗是至關很差的,因此通常會將異常進行捕獲處理,因爲異常信息容易讓開發者進行問題排查,因此通常會將其以日誌的形式記錄;系統中確定會考慮不少異常的地方,不可能到處都進行手動捕獲一下再處理,顯得代碼臃腫的同時還很差維護,因此用異常過濾器統一進行捕獲處理就顯得頗有必要了,固然,一些很關鍵的業務能夠進行單獨捕獲處理;異常過濾使用以下:
將其全局註冊,看運行效果:
小夥伴看到這,有沒好奇爲何不在受權過濾器和資源過濾器中拋出異常測試,而是選擇在Action方法中拋出異常,還記得第一張圖過濾器順序嗎(小夥伴再去重溫一下~),那是由於受權過濾器和資源過濾器那尚未異常過濾器,因此發生異常時捕獲不到,這也是小夥伴要特別注意的,須要本身處理好異常;只要在異常過濾器以後請求處理的異常都能捕獲到啦;
Action過濾器(Action Filter)
Action過濾器有前置和後置兩種方法,通常偏向於業務使用,好比在前置方法中進行驗證模型綁定參數的合法性,也能夠對參數進行加工等;後置方法能夠對返回結果的處理;
平時用的比較多,以下:
全局註冊,運行以下:
有沒有想試一下,在Action過濾器方法中拋出異常時,看看異常過濾器能不能捕獲到,答案確定是:能,但在這不截圖給小夥伴們看,小夥伴們動手試試嘛。
Result過濾器(Result Filter)
Result過濾器也有前置和後置兩種方法,前置方法能夠在結果沒返回前,能夠對Action返回的結果進行干預處理,後置方法通常是結果已經渲染以後執行;
API項目用的很少,在MVC Web項目比較適用,使用方式以下:
將其進行全局註冊,運行以下:
一樣在此過濾器中拋出異常,異常過濾器捕獲不到啦。
意不意外,驚不驚喜,其實只要開始進行響應結果處理時,異常過濾器就不捕獲對應異常,須要本身單獨處理;
過濾器的註冊範圍
除了上面的全局註冊,過濾器還能夠以特性的方式標註在控制器或對應Action方法上:
全局註冊:針對系統中全部過濾器都有效;
標註在控制器上(Controller):對標註控制器中全部Action方法都有效;
標註在Action上:只針對對應的Action有效;
思路:若是有極個別Action不想使用統一的過濾器,能夠經過標註特性的方式在對應過濾器邏輯中將其進行過濾掉。
過濾器註冊方式
全局方式註冊
在Startup中ConfigureServices註冊服務時全局註冊過濾器,以下圖:
特性方式標註
A、繼承Attribute類時,能夠直接標註在控制器(Controller)和Action上,以下圖:
B、沒有繼承Attribute類的狀況,借用TypeFilter、ServiceFilter或自定義IFilterFactory進行特性標註。
TypeFilter的方式,以下圖:
ServiceFilter的方式須要單獨註冊一下過濾器服務,控制生命週期,若是沒有註冊過濾器服務會報異常,以下圖:
註冊過濾器服務就正常了,以下圖:
自定義IFilterFactory,先實現一個特性類,以下:
使用以下:
同種過濾器的執行順序
對於不一樣類型過濾器的執行順序,開篇的圖就說明了,接下來講多個同種過濾器的執行順序;
不一樣範圍的同種過濾器順序
上面說到過濾的註冊範圍,有全局註冊、控制器標註、Action標註,同種過濾器在不一樣範圍註冊是什麼個順序?這裏以經常使用的Action過濾器爲例,其餘過濾器的練習就交給小夥伴了,這裏複製出MyActionFilter兩份,分別更名爲MyActionFilter1和MyActionFilter2,其中MyActionFilter用於全局註冊,MyActionFilter1用於控制器特性標註,MyActionFilter2用於Action方法標註,運行結果以下:
結論:全局註冊->控制器->Action。
相同範圍的同種過濾器順序
將MyActionFilter、MyActionFilter1和MyActionFilter2三個過濾器都標註在Action上,全局和控制器上都註釋掉,看效果:
結論:默認狀況註冊或特性標註順序與執行順序一致。
到這可能小夥伴會想:終於結束啦!!!,哈哈哈,nonono,對於過濾器的執行順序,除了以上默認順序以外,是能夠任意調整的,經過實現IOrderedFilter接口,設置對應過濾器的順序屬性便可改變對應的順序,Order值越小,優先級就越高,以下使用:
沒有效果圖,差評? 別別別,這裏是督促小夥伴本身試一把,否則小夥伴看一下就完事了(不本身操做一把,過兩天就會忘),有沒有用心良苦~
重點:Order排序優先於範圍排序,即先會以Order進行排序,若是一致,再以註冊的範圍排序。
總結
好啦,完啦!主要分享了MVC各類過濾器的使用,大概的應用場景,執行順序,註冊範圍及註冊方式。有沒有感受脖子有點小酸,來,起來走走,仰着頭的那種,標題是否是沒騙小夥伴,絕對真實。 下一篇說說MediatR組件和中介者設計模式。
整理了一些面試資料,關注公衆號「Code綜藝圈」,發送"面試"獲取下載地址,至於教程,手裏的也有一些Web前端、.Net後端、Java的教程,但如今網上資源比較多,大部分小夥伴喜歡在線看;若是有須要,小夥伴能夠私聊我,目前先把面試相關的資料放上去,收集內容會持續更新,包含一些大廠面試題,助力小夥伴找到心儀的工做:
教程截取部分圖以下,有須要私聊我:
一個被程序搞醜的帥小夥,關注"Code綜藝圈",識別關注跟我一塊兒學~~~
擼文不易,莫要白瞟,三連走起~~~~